CIpSocket::t_string CIpSocket::RecvFrom( unsigned long x_uMax, unsigned long x_uFlags ) { // Do we have a size limit? if ( 0 < x_uMax ) { // Allocate buffer t_string sBuf; try{ sBuf.resize( x_uMax ); } catch( ... ) { return sBuf; } if ( sBuf.length() >= x_uMax ) { // Attempt to read data unsigned int uRead = RecvFrom( &sBuf[ 0 ], x_uMax, 0, x_uFlags ); // Accept as the length sBuf.resize( uRead ); } // end if return sBuf; } // end if // Allocate buffer t_string sBuf; unsigned int uRead = 0, uOffset = 0; // Allocate space const unsigned int uMin = 1024; try{ sBuf.resize( uMin ); } catch( ... ) { return sBuf; } if ( sBuf.length() < uMin ) return sBuf; // Read all available data while ( 0 < ( uRead = RecvFrom( &sBuf[ uOffset ], uMin, 0, x_uFlags ) ) && uRead >= (unsigned int)uMin ) { // Allocate more space uOffset += uRead; try{ sBuf.resize( uOffset + uMin ); } catch( ... ) { return sBuf; } if ( sBuf.length() < uOffset + uMin ) return sBuf; } // end while // Set the length sBuf.resize( uOffset + uRead ); return sBuf; }
bool MockUDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, ola::network::IPV4Address &source) const { // NOLINT uint16_t port; return RecvFrom(buffer, data_read, source, port); }
int CTCPConnect::GetCustLevel(CString StrCardNum,CString strIP,CString strPort,UINT iOverTime) { if (StartSocket(strPort,strIP)) { char cCardNum[30]; CCommonConvert::CStringToChar(StrCardNum,cCardNum); SocketPackage package = MakePackage(cCardNum); int size = sizeof(package); SendTo((char*)&package,sizeof(package)); CString CardNum = _T("cardnum:")+StrCardNum; WriteLogWithTime(CardNum); char CardRecv[255]; BOOL RecvTemp = FALSE; setsockopt(m_tSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&iOverTime,sizeof(UINT)); if (!RecvFrom(CardRecv,255)) { return -1; } int iLevel = GetLevel(CardRecv); //RecvFrom() CloseSocket(); return iLevel; } else { CString strErr = _T("socket启动失败"); return -1; } }
long SDMDeletesub::Recv(long port) { int result; result = RecvFrom(port); if (result <= 0) return SDM_MESSAGE_RECV_ERROR; return result; }
int MySocket::RecvFrom(void *buf, int bytes, int flags) // Receive a block of data from a remote datagram socket // and do not return until all the bytes have been read. // Returns the total number of bytes received or -1 if // an error occurs. { return RecvFrom(Mysocket, &remote_sin, buf, bytes, flags); }
int MySocket::RecvFrom(void *buf, int bytes, int seconds, int useconds, int flags) // Receive a block of data from a remote datagram socket // and do not return until all the bytes have been read // or the timeout value has been exceeded. Returns the total // number of bytes received or -1 if an error occurs. { return RecvFrom(Mysocket, &remote_sin, buf, bytes, seconds, useconds, flags); }
int Socket::RecvFrom (uint8_t* buf, uint32_t size, uint32_t flags, Address &fromAddress) { NS_LOG_FUNCTION (this << &buf << size << flags << &fromAddress); Ptr<Packet> p = RecvFrom (size, flags, fromAddress); if (p == 0) { return 0; } p->CopyData (buf, p->GetSize ()); return p->GetSize (); }
bool MockUDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, ola::network::IPV4SocketAddress *source) { // NOLINT IPV4Address source_ip; uint16_t port; bool ok = RecvFrom(buffer, data_read, source_ip, port); if (ok) { *source = IPV4SocketAddress(source_ip, port); } return ok; }
//////////////////////////////////////////////////////////////////////////////// // 函数名:BOOL RecvFrom( // OUT LPSTR pszFrom, // OUT INT& nFromPort, // OUT CHAR *pszBuffer, // IN INT nBufferSize, // IN DWORD dwTimeout /*= DEFAULT_RECV_TIMEOUT*/ ) // 用 途:接收数据报 // 对全局变量的影响:无 // 参 数: // pszFrom : 源地址 // nFromPort : 源地址端口 // pszBuffer : 缓冲区 // nBufferSize : 缓冲区大小 // dwTimeout : 超时 // 返回值:BOOL //////////////////////////////////////////////////////////////////////////////// BOOL CBufSocket::RecvFrom(OUT LPSTR pszFrom,OUT INT& nFromPort,OUT CHAR *pszBuffer,IN INT nBufferSize,IN DWORD dwTimeout /*= DEFAULT_RECV_TIMEOUT*/) { SOCKADDR_IN sockAddrFrom; ZeroMemory(&sockAddrFrom,sizeof(sockAddrFrom)); // 假设缓冲区足够大,不考虑缓冲区不够的情形 if( RecvFrom(m_hSocket, (SOCKADDR *)&sockAddrFrom, sizeof(sockAddrFrom),pszBuffer,nBufferSize,dwTimeout) <= 0 ) return FALSE; // 保存源地址 LPSTR pFrom = inet_ntoa(sockAddrFrom.sin_addr); memcpy( pszFrom,pFrom,strlen(pFrom) ); nFromPort = ntohs( sockAddrFrom.sin_port); return TRUE; }
int DzRecvFrom( int fd, void* buf, size_t len, int flags, struct sockaddr* from, socklen_t* fromlen ) { DzHost* host = GetHost(); assert( host ); assert( fd >= 0 ); assert( ( fd & HANDLE_HOST_ID_MASK ) == host->hostId ); return RecvFrom( host, fd, buf, len, flags, from, fromlen ); }
void UDPStream::FlushRecv() { struct timeval time_val; time_val.tv_sec = 0; time_val.tv_usec = 0; fd_set rset; FD_ZERO(&rset); FD_SET(m_socket, &rset); if(select(static_cast<int>(m_socket + 1), &rset, NULL, NULL, &time_val) >= 0) { if(FD_ISSET(m_socket, &rset) > 0) { RecvFrom(); } } }
// Attempts Radius authentication (with specifying retry interval and multiple server) bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20) { UCHAR random[MD5_SIZE]; UCHAR id; BUF *encrypted_password = NULL; BUF *user_name = NULL; //IP ip; bool ret = false; TOKEN_LIST *token; UINT i; LIST *ip_list; IPC_MSCHAP_V2_AUTHINFO mschap; bool is_mschap; char client_ip_str[MAX_SIZE]; static UINT packet_id = 0; // Validate arguments if (server == NULL || port == 0 || (secret_size != 0 && secret == NULL) || username == NULL || password == NULL) { return false; } Zero(client_ip_str, sizeof(client_ip_str)); if (c != NULL && c->FirstSock != NULL) { IPToStr(client_ip_str, sizeof(client_ip_str), &c->FirstSock->RemoteIP); } // Parse the MS-CHAP v2 authentication data Zero(&mschap, sizeof(mschap)); is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, password); // Split the server into tokens token = ParseToken(server, " ,;\t"); // Get the IP address of the server ip_list = NewListFast(NULL); for(i = 0; i < token->NumTokens; i++) { IP *tmp_ip = Malloc(sizeof(IP)); if (GetIP(tmp_ip, token->Token[i])) { Add(ip_list, tmp_ip); } else if (GetIPEx(tmp_ip, token->Token[i], true)) { Add(ip_list, tmp_ip); } else { Free(tmp_ip); } } FreeToken(token); if(LIST_NUM(ip_list) == 0) { ReleaseList(ip_list); return false; } // Random number generation Rand(random, sizeof(random)); // ID generation id = (UCHAR)(packet_id % 254 + 1); packet_id++; if (is_mschap == false) { // Encrypt the password encrypted_password = RadiusEncryptPassword(password, random, secret, secret_size); if (encrypted_password == NULL) { // Encryption failure ReleaseList(ip_list); return false; } } // Generate the user name packet user_name = RadiusCreateUserName(username); if (user_name != NULL) { // Generate a password packet BUF *user_password = (is_mschap ? NULL : RadiusCreateUserPassword(encrypted_password->Buf, encrypted_password->Size)); BUF *nas_id = RadiusCreateNasId(CEDAR_SERVER_STR); if (is_mschap || user_password != NULL) { UINT64 start; UINT64 next_send_time; UCHAR tmp[MAX_SIZE]; UINT recv_buf_size = 32768; UCHAR *recv_buf = MallocEx(recv_buf_size, true); // Generate an UDP packet BUF *p = NewBuf(); UCHAR type = 1; SOCK *sock; USHORT sz = 0; UINT pos = 0; BOOL *finish = ZeroMallocEx(sizeof(BOOL) * LIST_NUM(ip_list), true); Zero(tmp, sizeof(tmp)); WriteBuf(p, &type, 1); WriteBuf(p, &id, 1); WriteBuf(p, &sz, 2); WriteBuf(p, random, 16); WriteBuf(p, user_name->Buf, user_name->Size); if (is_mschap == false) { UINT ui; // PAP WriteBuf(p, user_password->Buf, user_password->Size); WriteBuf(p, nas_id->Buf, nas_id->Size); // Service-Type ui = Endian32(2); RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); // NAS-Port-Type ui = Endian32(5); RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); // Calling-Station-Id RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); } else { // MS-CHAP v2 static UINT session_id = 0; USHORT us; UINT ui; char *ms_ras_version = "MSRASV5.20"; UCHAR ms_chapv2_response[50]; // Acct-Session-Id us = Endian16(session_id % 254 + 1); session_id++; RadiusAddValue(p, 44, 0, 0, &us, sizeof(us)); // NAS-IP-Address if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false) { ui = IPToUINT(&c->FirstSock->LocalIP); RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui)); } // Service-Type ui = Endian32(2); RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); // MS-RAS-Vendor ui = Endian32(311); RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui)); // MS-RAS-Version RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version)); // NAS-Port-Type ui = Endian32(5); RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); // Calling-Station-Id RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); // MS-RAS-Client-Version RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version)); // MS-RAS-Client-Name RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str)); // MS-CHAP-Challenge RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge)); // MS-CHAP2-Response Zero(ms_chapv2_response, sizeof(ms_chapv2_response)); Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16); Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24); RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response)); // NAS-ID WriteBuf(p, nas_id->Buf, nas_id->Size); } SeekBuf(p, 0, 0); WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size); // Create a socket sock = NewUDPEx(0, IsIP6(LIST_DATA(ip_list, pos))); // Transmission process start start = Tick64(); if(interval < RADIUS_RETRY_INTERVAL) { interval = RADIUS_RETRY_INTERVAL; } else if(interval > RADIUS_RETRY_TIMEOUT) { interval = RADIUS_RETRY_TIMEOUT; } next_send_time = start + (UINT64)interval; while (true) { UINT server_port; UINT recv_size; //IP server_ip; SOCKSET set; UINT64 now; SEND_RETRY: //SendTo(sock, &ip, port, p->Buf, p->Size); SendTo(sock, LIST_DATA(ip_list, pos), port, p->Buf, p->Size); Debug("send to host:%u\n", pos); next_send_time = Tick64() + (UINT64)interval; RECV_RETRY: now = Tick64(); if (next_send_time <= now) { // Switch the host to refer pos++; pos = pos % LIST_NUM(ip_list); goto SEND_RETRY; } if ((start + RADIUS_RETRY_TIMEOUT) < now) { // Time-out break; } InitSockSet(&set); AddSockSet(&set, sock); Select(&set, (UINT)(next_send_time - now), NULL, NULL); recv_size = RecvFrom(sock, LIST_DATA(ip_list, pos), &server_port, recv_buf, recv_buf_size); if (recv_size == 0) { Debug("Radius recv_size 0\n"); finish[pos] = TRUE; for(i = 0; i < LIST_NUM(ip_list); i++) { if(finish[i] == FALSE) { // Switch the host to refer pos++; pos = pos % LIST_NUM(ip_list); goto SEND_RETRY; } } // Failure break; } else if (recv_size == SOCK_LATER) { // Waiting goto RECV_RETRY; } else { // Check such as the IP address if (/*Cmp(&server_ip, &ip, sizeof(IP)) != 0 || */server_port != port) { goto RECV_RETRY; } // Success if (recv_buf[0] == 2) { ret = true; if (is_mschap && mschap_v2_server_response_20 != NULL) { // Cutting corners Zurukko UCHAR signature[] = {0x1A, 0x33, 0x00, 0x00, 0x01, 0x37, 0x1A, 0x2D, 0x00, 0x53, 0x3D, }; UINT i = SearchBin(recv_buf, 0, recv_buf_size, signature, sizeof(signature)); if (i == INFINITE || ((i + sizeof(signature) + 40) > recv_buf_size)) { ret = false; } else { char tmp[MAX_SIZE]; BUF *b; Zero(tmp, sizeof(tmp)); Copy(tmp, recv_buf + i + sizeof(signature), 40); b = StrToBin(tmp); if (b != NULL && b->Size == 20) { WHERE; Copy(mschap_v2_server_response_20, b->Buf, 20); } else { WHERE; ret = false; } FreeBuf(b); } } } break; } } Free(finish); // Release the socket ReleaseSock(sock); FreeBuf(p); FreeBuf(user_password); Free(recv_buf); } FreeBuf(nas_id); FreeBuf(user_name); } // Release the ip_list for(i = 0; i < LIST_NUM(ip_list); i++) { IP *tmp_ip = LIST_DATA(ip_list, i); Free(tmp_ip); } ReleaseList(ip_list); // Release the memory FreeBuf(encrypted_password); return ret; }
void udp_relayX(Connection *Conn,int csc,int csv[]) { int svsock; int sockv[1024],readyv[1024],sx; /* must be lt/eq FD_SESIZE */ int nsock; /* number of clients */ CStr(buff,0x8000); int rcc,wcc; int nready; CStr(ihost,64); int iport; CStr(svhost,64); int svport; const char *clhost; int clport; UDP_Assoc *ua; UDP_Assoc *udpav[MAXASSOC*4]; /**/ int udpxv[MAXASSOC*4]; int lastrelay,idle; const char *aaddr; int svportmap; int portnumv[64]; int csi; int istcp[MAXASSOC]; int ccc = 0; /* tcp clients */ int usocks = 0; /* UDP SOCKS */ int update = 0; int ai; /* is this necessary or effective ? */ socks_addservers(); if( MAXASSOC < UDPRELAY_MAXASSOC ){ UDPRELAY_MAXASSOC = MAXASSOC; } sv1log("MAXIMA=udprelay:%d (max. udp assoc.)\n",UDPRELAY_MAXASSOC); if( (aaddr = gethostaddr(DST_HOST)) == NULL ){ sv1log("#### ERROR: bad destination host [%s]\n",DST_HOST); return; } strcpy(svhost,aaddr); svport = DST_PORT; svportmap = DFLT_PORTMAP; if( svportmap ){ /* get port numbers of incoming ports ... */ for( csi = 0; csi < csc; csi++ ){ portnumv[csi] = sockPort(csv[csi]) + svportmap; portnumv[csi] &= ~0x40000000; /* clear IS_PORTMAP */ } } expand_fdset(MAXASSOC); uassocv = (UDP_Assoc**)calloc(MAXASSOC+1,sizeof(UDP_Assoc*)); for( csi = 0; csi < csc; csi++ ) sockv[csi] = csv[csi]; for( csi = 0; csi < csc; csi++ ) istcp[csi] = !isUDPsock(sockv[csi]); nsock = 0; lastrelay = 0; for(;;){ UPDATE: if( update ){ int ai; update = 0; ccc = 0; for( ai = 0; ua = uassocv[ai]; ai++ ){ if( ua->ua_clpriv ){ udpxv[csc + ccc] = ai; udpav[csc + ccc] = ua; sockv[csc + ccc++] = ua->ua_clsock; } } nsock = 0; for( ai = 0; ua = uassocv[ai]; ai++ ){ udpxv[csc+ccc + nsock] = ai; udpav[csc+ccc + nsock] = ua; sockv[csc+ccc + nsock++] = ua->ua_svsock; } usocks = 0; for( ai = 0; ua = uassocv[ai]; ai++ ){ int ns = csc+ccc+nsock; if( 0 <= ua->ua_svSOCKS ){ udpxv[ns+usocks] = ai; udpav[ns+usocks] = ua; sockv[ns+usocks] = ua->ua_svSOCKS; usocks++; } } } /* nready = PollIns(10*1000,csc+nsock+ccc,sockv,readyv); */ nready = PollIns(10*1000,csc+ccc+nsock+usocks,sockv,readyv); if( nready < 0 ){ /* sv1log("UDPRELAY: ABORT PollIns(%d) = %d\n",nready); */ sv1log("UDPRELAY: ABORT PollIns(%d+%d+%d+%d)=%d\n", csc,ccc,nsock,usocks,nready); for( ai = 0; ai < csc+ccc+nsock+usocks; ai++ ){ sv1log("[%2d] %d\n",ai,sockv[ai]); } break; } if( nready == 0 ){ idle = time(0) - lastrelay; if( SERVER_TIMEOUT && lastrelay ) if( SERVER_TIMEOUT < idle){ sv1log("UDPRELAY: SERVER TIMEOUT (idle %ds)\n", idle); break; } killTimeouts(uassocv); /* nsock = getsocks(uassocv,&sockv[csc]); */ update = 1; continue; } lastrelay = time(0); for( sx = 0; sx < csc; sx++ ) if( 0 < readyv[sx] && istcp[sx] ){ CStr(local,256); CStr(remote,256); int clsk; strcpy(remote,"*:*"); strcpy(local,"*:*"); clsk = VSocket(Conn,"ACPT/",sockv[sx],AVStr(local),AVStr(remote),""); /* setNonblockingIO("UDPRELAY-CL",clsk,1); */ SetNonblockingIO("UDPRELAY-CL",clsk,1); iport = getpeerAddr(clsk,AVStr(ihost)); if( clsk <= 0 || iport <= 0 ){ sv1log("UDPRELAY: accept() errno=%d\n",errno); continue; } if( svportmap ){ svport = portnumv[sx]; } ua = newUA(Conn,uassocv,ihost,iport,svhost,svport); ua->ua_clsock = clsk; ua->ua_clpriv = 1; update = 1; }else if( 0 < readyv[sx] ){ rcc = recvFromA(sockv[sx],AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport); if( rcc <= 0 ){ sv1log("UDPRELAY: recv() == 0, errno=%d\n",errno); break; } if( svportmap ){ svport = portnumv[sx]; } ua = findUAbysrc(uassocv,ihost,iport,svhost,svport); if( ua == NULL ){ ua = newUA(Conn,uassocv,ihost,iport,svhost,svport); if( ua == NULL ){ continue; } ua->ua_clsock = sockv[sx]; if( ua->ua_svsock < 0 ) continue; /* nsock = getsocks(uassocv,&sockv[csc]); */ update = 1; } toServ(ua,buff,rcc,svhost,svport,ihost,iport); /* ua->ua_mtime = time(0); ua->ua_upcnt++; ua->ua_upbytes += rcc; if( UDPRELAY_RPORT_FIX ) wcc = Send(ua->ua_svsock,buff,rcc); else wcc = SendTo(ua->ua_svsock,buff,rcc,svhost,svport); Verbose("TO SERV#%d: %s:%d %3d> %s:%d\n", ua->ua_id,ihost,iport,rcc,svhost,svport); */ if( nready == 1 ) continue; } for( sx = csc; sx < csc+ccc; sx++ ) if( 0 < readyv[sx] ){ rcc = recv(sockv[sx],buff,sizeof(buff),0); if( rcc <= 0 ){ int ux = getUAx(uassocv,udpav[sx]); if( ux < 0 ){ sv1log("## delUA-CL(%d)?\n",ux); continue; } delUA(uassocv,ux,"TCPreset-CL",1); /* here udpxv[] becomes inconsistent */ update = 1; }else{ ua = udpav[sx]; toServ(ua,buff,rcc,svhost,svport,NULL,0); } } /* for( sx = csc; sx < csc+nsock; sx++ ){ */ for( sx = csc+ccc; sx < csc+ccc+nsock; sx++ ){ if( readyv[sx] <= 0 ) continue; ua = udpav[sx]; svsock = sockv[sx]; if( 0 <= ua->ua_svSOCKS ) rcc = RecvFrom(svsock,buff,sizeof(buff),AVStr(ihost),&iport); else rcc = recvFromA(svsock,AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport); if( rcc <= 0 ){ if( ua->ua_svtcp ){ int ux = getUAx(uassocv,udpav[sx]); if( ux < 0 ){ sv1log("## delUA-SV(%d)?\n",ux); continue; } delUA(uassocv,ux,"TCPreset-SV",1); update = 1; } readyv[sx] = -1; continue; } /* ua = findUAbysock(uassocv,svsock); */ ua->ua_mtime = time(0); ua->ua_downcnt++; ua->ua_downbytes += rcc; clhost = ua->ua_clhost; clport = ua->ua_clport; /* wcc = SendTo(ua->ua_clsock,buff,rcc,clhost,clport); */ wcc = sendToA(ua->ua_clsock,buff,rcc,0,clhost,clport); Verbose("TO CLNT#%d: %s:%d <%-3d %s:%d\n", ua->ua_id,clhost,clport,rcc,ihost,iport); } for( sx = csc+ccc+nsock; sx < csc+ccc+nsock+usocks; sx++ ){ int ux; if( readyv[sx] <= 0 ) continue; ua = udpav[sx]; ux = getUAx(uassocv,udpav[sx]); if( ux < 0 ){ sv1log("## delUA-CTL(%d)?\n",ux); continue; } sv1log("## detected disconn. by SOCKS CTL [%d]\n",ux); delUA(uassocv,ux,"SOCKSCTLreset-SV",1); update = 1; } } }
Ptr<Packet> Socket::RecvFrom (Address &fromAddress) { NS_LOG_FUNCTION (this << &fromAddress); return RecvFrom (std::numeric_limits<uint32_t>::max (), 0, fromAddress); }
bool NetBase::CheckIn() { // check for incoming packets SOCKADDR_IN addr; memset (&addr, 0, sizeof(SOCKADDR_IN)); socklen_t len = sizeof(SOCKADDR_IN); if (!input_buffer) { input_buffer = (char*) cs_malloc(MAXPACKETSIZE); if (!input_buffer) { Error2("Failed to cs_malloc %d bytes for packet buffer!\n",MAXPACKETSIZE); return false; } } // Connection must be initialized! CS_ASSERT(ready); int packetlen = RecvFrom (&addr, &len, (void*) input_buffer, MAXPACKETSIZE); if (packetlen <= 0) { return false; } // Identify the connection Connection* connection = GetConnByIP(&addr); // Extract the netpacket from the buffer and prep for use locally. psNetPacket *bufpacket = psNetPacket::NetPacketFromBuffer(input_buffer,packetlen); if (bufpacket==NULL) { char addrText[INET_ADDRSTRLEN]; //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista. //it has the same degree of compatibility of the previous code and it's supported till win2000 #ifdef WIN32 strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN); #else //there was a failure in conversion if null if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText))) { strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN); } #endif // The data received was too small to make a full packet. if (connection) { Debug4(LOG_NET, connection->clientnum, "Too short packet received from client %d (IP: %s) (%d bytes)", connection->clientnum, addrText, packetlen); } else { Debug3(LOG_NET, 0, "Too short packet received from IP address %s. (%d bytes) No existing connection from this IP.", addrText, packetlen); } return true; // Continue processing more packets if available } input_buffer = NULL; //input_buffer now hold by the bufpacket pointer. // Endian correction bufpacket->UnmarshallEndian(); // Check for too-big packets - no harm in processing them, but probably a bug somewhere if (bufpacket->GetPacketSize() < static_cast<unsigned int>(packetlen)) { char addrText[INET_ADDRSTRLEN]; //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista. //it has the same degree of compatibility of the previous code and it's supported till win2000 #ifdef WIN32 strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN); #else //there was a failure in conversion if null if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText))) { strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN); } #endif if (connection) { Debug5(LOG_NET, connection->clientnum, "Too long packet received from client %d (IP: %s) (%d bytes received, header reports %zu bytes)", connection->clientnum, addrText, packetlen, bufpacket->GetPacketSize()); } else { Debug4(LOG_NET, 0,"Too long packet received from IP address %s. (%d bytes received, header reports %zu bytes) No existing connection from this IP.", addrText, packetlen, bufpacket->GetPacketSize()); } } //Create new net packet entry and transfer ownership of bufpacket to pkt. csRef<psNetPacketEntry> pkt; pkt.AttachNew(new psNetPacketEntry( bufpacket, connection ? connection->clientnum : 0, packetlen)); if(TEST_PACKETLOSS > 0.0 && randomgen->Get() < TEST_PACKETLOSS) { psNetPacket* packet = pkt->packet; int type = 0; if (packet->offset == 0) { psMessageBytes* msg = (psMessageBytes*) packet->data; type = msg->type; } Error3("Packet simulated lost. Type %s ID %d.\n", type == 0 ? "Fragment" : (const char *) GetMsgTypeName(type), pkt->packet->pktid); return true; } // ACK packets can get eaten by HandleAck if (HandleAck(pkt, connection, &addr)) { return true; } // printf("Got packet with sequence %d.\n", pkt->packet->GetSequence()); // // Check for doubled packets and drop them if (pkt->packet->pktid != 0) { if (connection && CheckDoublePackets (connection, pkt)) { #ifdef PACKETDEBUG Debug2(LOG_NET,0,"Dropping doubled packet (ID %d)\n", pkt->packet->pktid); #endif return true; } } #ifdef PACKETDEBUG Debug7(LOG_NET,0,"Received Pkt, ID: %d, offset %d, from %d size %d (actual %d) flags %d\n", pkt->packet->pktid, pkt->packet->offset, pkt->clientnum, pkt->packet->pktsize,packetlen, pkt->packet->flags); #endif /** * Now either send this packet to BuildMessage, or loop through * subpackets if they are merged. */ csRef<psNetPacketEntry> splitpacket = pkt; psNetPacket *packetdata = NULL; do { splitpacket = pkt->GetNextPacket(packetdata); if (splitpacket) BuildMessage(splitpacket, connection, &addr); } while (packetdata); return true; }
bool MockUDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read) const { IPV4Address address; uint16_t port; return RecvFrom(buffer, data_read, address, port); }
// Polling process void UdpAccelPoll(UDP_ACCEL *a) { UCHAR *tmp = a->TmpBuf; IP nat_t_ip; UINT num_ignore_errors = 0; // Validate arguments if (a == NULL) { return; } Lock(a->NatT_Lock); { Copy(&nat_t_ip, &a->NatT_IP, sizeof(IP)); } Unlock(a->NatT_Lock); if (IsZeroIp(&nat_t_ip) == false) { // Release the thread which gets the IP address of the NAT-T server because it is no longer needed if (a->NatT_GetIpThread != NULL) { WaitThread(a->NatT_GetIpThread, INFINITE); ReleaseThread(a->NatT_GetIpThread); a->NatT_GetIpThread = NULL; } } // Receive a new UDP packet while (true) { IP src_ip; UINT src_port; UINT ret; ret = RecvFrom(a->UdpSock, &src_ip, &src_port, tmp, UDP_ACCELERATION_TMP_BUF_SIZE); if (ret != 0 && ret != SOCK_LATER) { if (a->UseUdpIpQuery && a->UdpIpQueryPacketSize >= 8 && CmpIpAddr(&a->UdpIpQueryHost, &src_ip) == 0 && src_port == a->UdpIpQueryPort) { // Receive a response of the query for IP and port number IP my_ip = {0}; UINT myport = 0; BUF *b = MemToBuf(a->UdpIpQueryPacketData, a->UdpIpQueryPacketSize); FreeBuf(b); } else if (IsZeroIp(&nat_t_ip) == false && CmpIpAddr(&nat_t_ip, &src_ip) == 0 && src_port == UDP_NAT_T_PORT) { // Receive a response from the NAT-T server IP my_ip; UINT myport; if (RUDPParseIPAndPortStr(tmp, ret, &my_ip, &myport)) { if (myport >= 1 && myport <= 65535) { if (a->MyPortByNatTServer != myport) { a->MyPortByNatTServer = myport; a->MyPortByNatTServerChanged = true; a->CommToNatT_NumFail = 0; Debug("NAT-T: MyPort = %u\n", myport); } } } /* BUF *b = NewBuf(); PACK *p; WriteBuf(b, tmp, ret); SeekBufToBegin(b); p = BufToPack(b); if (p != NULL) { if (PackCmpStr(p, "opcode", "query_for_nat_traversal")) { if (PackGetBool(p, "ok")) { if (PackGetInt64(p, "tran_id") == a->NatT_TranId) { UINT myport = PackGetInt(p, "your_port"); if (myport >= 1 && myport <= 65535) { if (a->MyPortByNatTServer != myport) { a->MyPortByNatTServer = myport; a->MyPortByNatTServerChanged = true; Debug("NAT-T: MyPort = %u\n", myport); } } } } } FreePack(p); } FreeBuf(b);*/ } else { BLOCK *b = UdpAccelProcessRecvPacket(a, tmp, ret, &src_ip, src_port); //Debug("UDP Recv: %u %u %u\n", ret, (b == NULL ? 0 : b->Size), (b == NULL ? 0 : b->Compressed)); /*if (b != NULL) { char tmp[MAX_SIZE * 10]; BinToStr(tmp, sizeof(tmp), b->Buf, b->Size); Debug("Recv Pkt: %s\n", tmp); }*/ if (b != NULL) { // Receive a packet InsertQueue(a->RecvBlockQueue, b); } } } else { if (ret == 0) { if (a->UdpSock->IgnoreRecvErr == false) { // Serious UDP reception error occurs a->FatalError = true; break; } if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS) { a->FatalError = true; break; } } else { // SOCK_LATER break; } } } // Send a Keep-Alive packet if (a->NextSendKeepAlive == 0 || (a->NextSendKeepAlive <= a->Now) || a->YourPortByNatTServerChanged) { a->YourPortByNatTServerChanged = false; if (UdpAccelIsSendReady(a, false)) { UINT rand_interval; if (a->FastDetect == false) { rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN; } else { rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST; } a->NextSendKeepAlive = a->Now + (UINT64)rand_interval; //Debug("UDP KeepAlive\n"); UdpAccelSend(a, NULL, 0, false, 1000, false); } } // Send a NAT-T request packet (Only if the connection by UDP has not be established yet) if (a->NoNatT == false) { // In the usual case if (IsZeroIp(&nat_t_ip) == false) { if (UdpAccelIsSendReady(a, true) == false) { if (a->NextPerformNatTTick == 0 || (a->NextPerformNatTTick <= a->Now)) { UINT rand_interval; UCHAR c = 'B'; a->CommToNatT_NumFail++; rand_interval = UDP_NAT_T_INTERVAL_INITIAL * MIN(a->CommToNatT_NumFail, UDP_NAT_T_INTERVAL_FAIL_MAX); //PACK *p = NewPack(); //BUF *b; if (a->MyPortByNatTServer != 0) { rand_interval = GenRandInterval(UDP_NAT_T_INTERVAL_MIN, UDP_NAT_T_INTERVAL_MAX); } a->NextPerformNatTTick = a->Now + (UINT64)rand_interval; // Generate the request packet /*PackAddStr(p, "description", UDP_NAT_T_SIGNATURE); PackAddStr(p, "opcode", "query_for_nat_traversal"); PackAddInt64(p, "tran_id", a->NatT_TranId); b = PackToBuf(p); FreePack(p);*/ // Send the request packet SendTo(a->UdpSock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1); //FreeBuf(b); } } else { a->NextPerformNatTTick = 0; a->CommToNatT_NumFail = 0; } } } else { // NAT_T is disabled, but there is a reference host (such as VGC) if (a->UseUdpIpQuery || a->UseSuperRelayQuery) { } } }
/*!\brief Lese-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Lesezugriffe gesetzt werden. Normalerweise * blockiert eine Leseoperation mit "Read" solange, bis die angeforderten Daten * eingegangen sind (ausser der Socket wurde mit TCPSocket::setBlocking auf "Non-Blocking" * gesetzt). Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutRead(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Schreib-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Schreibzugriffe gesetzt werden. Normalerweise * blockiert eine Schreiboperation mit "Write" solange, bis alle Daten gesendet wurden. * Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutWrite(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Auf eingehende Daten warten * * \desc * Diese Funktion prüft, ob Daten eingegangen sind. Ist dies der Fall, * kehrt sie sofort wieder zurück. Andernfalls wartet sie solange, bis * Daten eingehen, maximal aber die mit \p seconds und \p useconds * angegebene Zeitspanne. Falls \p seconds und \p useconds Null sind, und * keine Daten bereitstehen, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten zum Lesen bereitstehen, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse */ bool UDPSocket::waitForIncomingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&rset); // Wir wollen nur prüfen, ob was zu lesen da ist int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } // Falls Daten zum Lesen bereitstehen, könnte dies auch eine Verbindungstrennung anzeigen if (FD_ISSET(s->sd,&rset)) { char buf[2]; ret=recv(s->sd, buf,1, MSG_PEEK|MSG_DONTWAIT); // Kommt hier ein Fehler zurück? if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::isReadable"); } // Ein Wert von 0 zeigt an, dass die Verbindung getrennt wurde if (ret==0) { throw BrokenPipeException(); } return true; } return false; } /*!\brief Warten, bis der Socket beschreibbar ist * * \desc * Diese Funktion prüft, ob Daten auf den Socket geschrieben werden können. * Ist dies der Fall, kehrt sie sofort wieder zurück. Andernfalls wartet * sie solange, bis der Socket beschrieben werden kann, maximal aber die * mit \p seconds und \p useconds angegebene Zeitspanne. * Falls \p seconds und \p useconds Null sind, und * keine Daten gesendet werden können, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten geschrieben werden können, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse * */ bool UDPSocket::waitForOutgoingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&wset); // Wir wollen nur prüfen, ob wir schreiben können int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForOutgoingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&wset)) { return true; } return false; } /*!\brief Bei Lesezugriffen blockieren * * \desc * Durch Aufruf dieser Funktion kann festgelegt werden, ob der Socket bei Lesezugriffen * blockieren soll. Nach dem Öffnen des Sockets ist dieser defaultmäßig so * eingestellt, dass er bei Lesezugriffen solange blockiert (wartet), bis Daten zur * Verfügung stehen. Wird er auf "Non-Blocking" gestellt, kehren die Lese-Funktionen * sofort mit einer Fehlermeldung zurück, wenn noch keine Daten bereitstehen. * * @param[in] value Der Wert "true" setzt den Socket in den Blocking-Modus, was auch der * Default ist. Durch den Wert "false" wird er in den Non-Blocking-Modus gesetzt. * @exception Diverse */ void UDPSocket::setBlocking(bool value) { PPLSOCKET *s=(PPLSOCKET*)socket; if((!s) || (!s->sd)) throw NotConnectedException(); int ret=0; #ifdef _WIN32 u_long v; if (value) { v=0; ret=ioctlsocket(s->sd,FIONBIO,NULL); } else { v=1; ret=ioctlsocket(s->sd,FIONBIO,&v); } if (ret==0) return; throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #else if (value) ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)&(~O_NONBLOCK)); // Blocking else ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)|O_NONBLOCK);// NON-Blocking if (ret<0) throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #endif } /*!\brief Socket auf eine IP-Adresse und Port binden * * \desc * Diese Funktion muss aufgerufen werden, bevor man mit CTCPSocket::Listen einen TCP-Server starten kann. Dabei wird mit \p host * die IP-Adresse festgelegt, auf die sich der Server binden soll und mit \p port der TCP-Port. * Es ist nicht möglich einen Socket auf mehrere Adressen zu binden. * * @param[in] host IP-Adresse, Hostname oder "*". Bei Angabe von "*" bindet sich der Socket auf alle * Interfaces des Servers. * @param[in] port Der gewünschte TCP-Port * @exception OutOfMemoryException * @exception ResolverException * @exception SettingSocketOptionException * @exception CouldNotBindToInterfaceException * @exception CouldNotOpenSocketException */ void UDPSocket::bind(const String &host, int port) { //int addrlen=0; if (!socket) { socket=malloc(sizeof(PPLSOCKET)); if (!socket) throw OutOfMemoryException(); PPLSOCKET *s=(PPLSOCKET*)socket; s->sd=0; s->proto=6; s->ipname=NULL; s->port=port; //s->addrlen=0; } #ifdef _WIN32 SOCKET listenfd=0; #else int listenfd=0; #endif PPLSOCKET *s=(PPLSOCKET*)socket; if (s->sd) disconnect(); if (s->ipname) free(s->ipname); s->ipname=NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags=AI_PASSIVE; hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; int on=1; // Prüfen, ob host ein Wildcard ist struct addrinfo *res; if (host.notEmpty()==true && host!="*") { char portstr[10]; sprintf(portstr,"%i",port); int n; if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) { throw ResolverException("%s, %s",(const char*)host,gai_strerror(n)); } struct addrinfo *ressave=res; do { listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol); if (listenfd<0) continue; // Error, try next one #ifdef _WIN32 if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) { #else if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))!=0) { #endif freeaddrinfo(ressave); throw SettingSocketOptionException(); } if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) { //addrlen=res->ai_addrlen; break; } ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif listenfd=0; } while ((res=res->ai_next)!=NULL); freeaddrinfo(ressave); } else { // Auf alle Interfaces binden listenfd=::socket(AF_INET, SOCK_STREAM, 0); if (listenfd>=0) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); addr.sin_family = AF_INET; /* bind server port */ if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) { ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif throw CouldNotBindToInterfaceException("Host: *, Port: %d",port); } s->sd=listenfd; connected=1; return; } } if (listenfd<0) { throw CouldNotOpenSocketException("Host: %s, Port: %d",(const char*)host,port); } if (res==NULL) { throw CouldNotBindToInterfaceException("Host: %s, Port: %d",(const char*)host,port); } s->sd=listenfd; connected=1; } /*!\brief Daten schreiben * * \desc * Mit dieser Funktionen werden \p bytes Bytes aus dem Speicherbereich \p buffer an die Gegenstelle * gesendet. * * @param[in] buffer Pointer auf die zu sendenden Daten * @param[in] bytes Anzahl zu sendender Bytes * @return Wenn die Daten erfolgreich geschrieben wurden, gibt die Funktion die Anzahl geschriebener * Bytes zurück. Im Fehlerfall wird eine Exception geworfen. */ size_t UDPSocket::write(const void *buffer, size_t bytes) { if (!connected) throw NotConnectedException(); PPLSOCKET *s = (PPLSOCKET*) socket; if (!buffer) throw InvalidArgumentsException(); size_t BytesWritten = 0; if (bytes) { size_t rest = bytes; ssize_t b = 0; while (rest) { b = ::send(s->sd, (char *) buffer, rest, 0); if (b > 0) { BytesWritten += b; rest -= b; buffer = ((const char*) buffer) + b; } #ifdef WIN32 if (b==SOCKET_ERROR) { #else if (b < 0) { #endif if (errno == EAGAIN) { waitForOutgoingData(0, 100000); } else { throwExceptionFromErrno(errno, "UDPSocket::write"); } } } } return BytesWritten; } size_t UDPSocket::write(const String &str, size_t bytes) { if (bytes>0 && bytes<=str.size()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.size()); } size_t UDPSocket::write(const WideString &str, size_t bytes) { if (bytes>0 && bytes<=str.byteLength()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.byteLength()); } size_t UDPSocket::write(const ByteArrayPtr &bin, size_t bytes) { if (bytes>0 && bytes<=bin.size()) { return write(bin.ptr(),bytes); } return write(bin.ptr(),bin.size()); } size_t UDPSocket::writef(const char *fmt, ...) { if (!fmt) throw IllegalArgumentException(); String str; va_list args; va_start(args, fmt); str.vasprintf(fmt,args); va_end(args); return write(str); } #ifdef TODO void UDPSocket::setTimeoutRead(int seconds, int useconds) /*! \brief Timeout setzen * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird der Timeout für das Empfangen von Daten gesetzt. * * \param seconds Anzahl Sekunden * \param useconds Anzahl Millisekunden * \note Diese Funktion hat zur Zeit noch keine Auswirkungen * \since Wurde mit Version 6.0.19 eingeführt */ { timeout_sec=seconds; timeout_usec=useconds; } #endif #ifdef TODO size_t UDPSocket::sendTo(const String &host, int port, const String &buffer) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf eine String-Klasse, die die zu sendenden Daten enthält * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { return sendTo(host,port,(const void *)buffer.getPtr(),buffer.len()); } size_t UDPSocket::sendTo(const String &host, int port, const void *buffer, size_t bytes) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf den Puffer, der die zu sendenden Daten enthält * \param bytes Die Anzahl Bytes im Puffer, die gesendet werden sollen * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { if (!host) { ppl6::SetError(194,"int UDPSocket::SendTo(==> char *host <== , int port, void *buffer, int bytes)"); return -1; } if (!port) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, ==> int port <== , void *buffer, int bytes)"); return -1; } if (!buffer) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, ==> void *buffer <== , int bytes)"); return -1; } if (bytes<0) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, void *buffer, ==> int bytes <== )"); return -1; } ppl6::CAssocArray res, *a; ppl6::CBinary *bin; if (!ppl6::GetHostByName(host,&res)) return -1; a=res.GetFirstArray(); //a->List(); int domain, type, protocol; domain=ppl6::atoi(a->Get("ai_family")); type=ppl6::atoi(a->Get("ai_socktype")); //protocol=ppl6::atoi(a->Get("ai_protocol")); struct protoent *proto=getprotobyname("UDP"); if (!proto) { ppl6::SetError(395); return -1; } protocol=proto->p_proto; bin=a->GetBinary("ai_addr"); //a->List(); const struct sockaddr *to=(const struct sockaddr *)bin->GetPtr(); ((sockaddr_in*)to)->sin_port=htons(port); PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { socket=malloc(sizeof(PPLSOCKET)); s=(PPLSOCKET*)socket; s->sd=-1; } else if ((int)s->sd>-1) { ppl_closesocket(s->sd); } s->sd=::socket(domain,SOCK_DGRAM,protocol); //sockfd=::socket(AF_INET,SOCK_DGRAM,0); if (s->sd<0) { SetSocketError(); return -1; } #ifdef _WIN32 int ret=::sendto(s->sd,(const char*)buffer,bytes,0,to,bin->GetSize()); #else ssize_t ret=::sendto(s->sd,(const void*)buffer,(size_t)bytes,0,to,(socklen_t) bin->GetSize()); #endif if (ret<0) { printf ("ret: %i\n",(int)ret); SetSocketError(); return -1; } //close(sockfd); return ret; } int UDPSocket::RecvFrom(CString &buffer, int maxlen) /*! \brief UDP-Packet empfangen * * \header \#include <ppl6.h> * \desc * Diese Funktion wartet auf ein UDP-Packet * * \param buffer Ein Pointer auf eine String-Klasse, in die die Daten geschrieben werden sollen * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { char *b=(char*)malloc(maxlen+1); if (!b) { SetError(2); return 0; } int ret=RecvFrom((void*)b,maxlen); buffer.ImportBuffer(b,maxlen); return ret; }
int service_sudo(Connection *Conn,int svsock,int svport){ int fc; int fv[2]; int rv[2]; CStr(req,1024); CStr(com,1024); CStr(arg,1024); CStr(a1,1024); CStr(a2,1024); CStr(a3,1024); const char *dp; CStr(resp,1024); int tsock = -1; int clsock; int isUDP; int rcc; int fd; CStr(local,MaxHostNameLen); CStr(remote,MaxHostNameLen); CStr(opts,MaxHostNameLen); CStr(clhost,128); int clport; gethostName(svsock,AVStr(local),"%A"); sv1log("==SU START uid=%d/%d sock=%d port=%d udp=%d [%s]\n", getuid(),geteuid(),svsock,svport,isUDPsock(svsock),local); if( svport == 0 ){ sprintf(local,"%s/sudo/port/P%s",DELEGATE_DGROOT,portSUDO); unlink(local); svsock = server_open_un("SUDO",AVStr(local),32); sv1log("==SU sock[%d] %s\n",svsock,local); if( svsock < 0 ){ return -1; } if( geteuid() == 0 ){ int omode = File_mod(local); /* set the owner of the socket to the one in OWNER */ chmodShared(local); chmod(local,omode|0660); } } if( isUDP = isUDPsock(svsock) ){ }else{ } if( isUDP ){ tsock = server_open_un("SUDO",AVStr(local),32); sv1log("---> tsock:%d [%s]\n",tsock,local); }else{ tsock = svsock; } fc = 1; fv[0] = tsock; if( 0 <= isPrivateSUDO ){ fc = 2; fv[1] = isPrivateSUDO; } for(;;){ /* if( PollIn(tsock,0) <= 0 ){ break; } */ if( PollIns(0,fc,fv,rv) <= 0 ){ sv1log("==SU EXIT: poll error\n"); break; } if( fc == 2 ){ if( rv[1] ){ sv1log("==SU EXIT: parent died\n"); break; } if( rv[0] == 0 ) continue; } clsock = tsock; if( !isUDP && !IsConnected(tsock,NULL) ){ clsock = ACCEPT1(tsock,1,-1,10,AVStr(clhost)); if( clsock < 0 ){ msleep(100); continue; } } rcc = RecvFrom(clsock,req,sizeof(req)-1,AVStr(clhost),&clport); if( rcc <= 0 ){ sv1log("==SU %d %d rcc=%d\n",tsock,clsock,rcc); if( clsock != tsock ){ close(clsock); continue; }else{ sv1log("==SU EXIT: read error\n"); break; } } setVStrEnd(req,rcc); dp = wordScan(req,com); if( *dp == ' ' ) textScan(dp+1,arg); else lineScan(dp,arg); dp = wordScan(arg,a1); dp = wordScan(dp,a2); lineScan(dp,a3); sv1log("==SU Q[%s][%s]\n",com,arg); putLoadStat(ST_ACC,1); putLoadStat(ST_DONE,1); put_svstat(); incRequestSerno(Conn); if( strcaseeq(com,"QUIT") ){ if( isUDP ){ continue; }else{ sv1log("==SU EXIT: by QUIT command\n"); break; } } if( strcaseeq(com,"PAM") ){ doPAM(clsock,clhost,clport,tsock,arg); continue; } if( strcaseeq(com,"BIND") ){ doBind(clsock,clhost,clport,tsock,arg); continue; } /* if( strcaseeq(com,"STDERR") ){ sv1log("==SU receiving @fd[%d]\n",usock); fd = recvFd(usock); fprintf(stderr,"---- STDERR %d -> %d\n",usock,fd); if( 0 <= fd ){ dup2(fd,fileno(stderr)); fprintf(stderr,"---- STDERR %d dup2\n",fd); } } */ } return 0; }
// UDP listener main loop void ListenerUDPMainLoop(LISTENER *r) { UCHAR *data; // Validate arguments if (r == NULL) { return; } Debug("ListenerUDPMainLoop Starts.\n"); r->Status = LISTENER_STATUS_TRYING; while (true) { // Try to listen on the UDP port while (true) { // Stop flag inspection if (r->Halt) { // Stop return; } Debug("NewUDP()\n"); r->Sock = NewUDP(r->Port); if (r->Sock != NULL) { // Wait success break; } // Wait failure Debug("Failed to NewUDP.\n"); Wait(r->Event, LISTEN_RETRY_TIME); // Stop flag inspection if (r->Halt) { Debug("UDP Halt.\n"); return; } } r->Status = LISTENER_STATUS_LISTENING; Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort); // Stop flag inspection if (r->Halt) { // Stop goto STOP; } // Allocate the buffer area data = Malloc(UDP_PACKET_SIZE); // Read the next packet while (true) { IP src_ip; UINT src_port; UINT size; SOCKSET set; InitSockSet(&set); AddSockSet(&set, r->Sock); Select(&set, SELECT_TIME, NULL, NULL); size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE); if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt) { // Error has occurred STOP: Disconnect(r->Sock); ReleaseSock(r->Sock); r->Sock = NULL; Debug("UDP Listen Stopped.\n"); Free(data); break; } // Received an UDP packet if (size != SOCK_LATER) { UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size); } } } }