/* Look up various bits of information related to a Socket instance and store them in the private member variables for future use. If this has already been called on a specific instance, do nothing. */ static AValue SocketGetInfo(AThread *t, AValue *frame) { if (AMemberDirect(frame[0], SOCKET_DST_ADDRESS) == ANil) { AValue v; SOCKLEN_T len; struct sockaddr_in address; int handle; handle = AGetInt(t, AMemberDirect(frame[0], A_FILE_ID)); len = sizeof(address); if (getsockname(handle, (struct sockaddr *)&address, &len) < 0) return RaiseSocketError(t); v = AMakeInt(t, ntohs(address.sin_port)); ASetMemberDirect(t, frame[0], SOCKET_SRC_PORT, v); /* FIX: inet_ntoa is not thread-safe */ v = AMakeStr(t, inet_ntoa(address.sin_addr)); ASetMemberDirect(t, frame[0], SOCKET_SRC_ADDRESS, v); len = sizeof(address); if (getpeername(handle, (struct sockaddr *)&address, &len) < 0) return RaiseSocketError(t); v = AMakeInt(t, ntohs(address.sin_port)); ASetMemberDirect(t, frame[0], SOCKET_DST_PORT, v); /* FIX: inet_ntoa is not thread-safe */ v = AMakeStr(t, inet_ntoa(address.sin_addr)); ASetMemberDirect(t, frame[0], SOCKET_DST_ADDRESS, v); } return ANil; }
void NetworkCommandBuffer::Think() { SDLNet_SocketSet set; set = SDLNet_AllocSocketSet ( 1 ); if ( !set ) { RaiseSocketError ( "SDLNet_AllocSocketSet" ); } SocketSetEncapsulator free_on_quit ( set ); if ( SDLNet_TCP_AddSocket ( set, socket ) < 0 ) { RaiseSocketError ( "SDLNet_TCP_AddSocket" ); } int numready = SDLNet_CheckSockets ( set, 0 ); for ( ; numready == 1; numready = SDLNet_CheckSockets ( set, 0 ) ) { char msg; int nbread = SDLNet_TCP_Recv ( socket, &msg, 1 ); if ( nbread < 0 ) { RaiseSocketError ( "SDLNet_TCP_Recv: " ); } else if ( nbread == 0 ) { std::cout << "SDLNet_TCP_Recv: Unexpected read of size 0\n"; throw ReadSocketError(); } if ( debug_all_message ) { if ( msg < 32 ) std::cout << "Read: 0x" << ( int ) msg << "\n"; else std::cout << "Read: " << msg << "\n"; } if (current_command_size > 0) AddCharToBuffer ( msg ); else AddCharToCommandSize( msg ); } if ( numready < 0 ) { std::cout << "SDLNet_CheckSockets: " << SDLNet_GetError() << "\n"; perror ( "SDLNet_CheckSockets" ); throw ReadSocketError(); } }
/* socket::GetHostName() */ static AValue SocketGetHostName(AThread *t, AValue *frame) { char buf[MAX_ADDRESS_LEN]; if (gethostname(buf, sizeof(buf)) < 0) return RaiseSocketError(t); return AMakeStr(t, buf); }
/* Socket create(destination, port[, buffering]) */ static AValue SocketCreate(AThread *t, AValue *frame) { char addressStr[MAX_ADDRESS_LEN]; int handle; struct sockaddr_in address; int port; /* Get host name. */ AGetStr(t, frame[1], addressStr, MAX_ADDRESS_LEN); /* Get port number. */ port = AGetInt(t, frame[2]); /* Get buffering mode. */ if (AIsDefault(frame[3])) frame[1] = AGlobalByNum(AUnbufferedNum); else if (frame[3] == AGlobalByNum(AUnbufferedNum) || frame[3] == AGlobalByNum(ALineBufferedNum) || frame[3] == AGlobalByNum(ABufferedNum)) frame[1] = frame[3]; else return ARaiseValueError(t, "Invalid arguments"); frame[2] = AGlobalByNum(AInputNum); frame[3] = AGlobalByNum(AOutputNum); frame[4] = AGlobalByNum(ANarrowNum); if (AIsError(AStreamCreate(t, frame))) return AError; /* Initialize address structure. */ memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = htons(port); /* GetHostByName can handle both numeric IP addresses and host names. */ if (!GetHostByName(t, addressStr, &address.sin_addr)) return AError; /* Create socket. */ handle = socket(AF_INET, SOCK_STREAM, 0); if (handle < 0) return RaiseSocketError(t); /* Create connection. */ for (;;) { int status; AAllowBlocking(); status = connect(handle, (struct sockaddr *)&address, sizeof(address)); AEndBlocking(); if (status < 0) { if (errno == EINTR) { if (AIsInterrupt && AHandleInterrupt(t)) return AError; else continue; } else { RaiseSocketError(t); close(handle); return AError; } } break; } frame[1] = AMakeInt(t, handle); ASetMemberDirect(t, frame[0], A_FILE_ID, frame[1]); return frame[0]; }