int initialize_acceptor(acceptor_t acceptor) { acceptor->fd = create_listener_socket(PORT); if (acceptor->fd == -1) { return -1; } event_set(&acceptor->event, acceptor->fd, EV_READ | EV_PERSIST, acceptor_handler, (void *)acceptor); event_add(&acceptor->event, NULL); return acceptor->fd; }
THREAD_CALL viewer_listen(LPVOID lpParam) { listener_thread_params *thread_params = (listener_thread_params *)lpParam; SOCKET conn; struct sockaddr_in client; socklen_t socklen = sizeof(client); rfbProtocolVersionMsg protocol_version; CARD32 auth_type; CARD32 auth_response; CARD8 client_init; unsigned char challenge[CHALLENGESIZE]; char *ip_addr; thread_params->sock = create_listener_socket( thread_params->port ); if (thread_params->sock == INVALID_SOCKET) notstopped = false; else logp(DEBUG, "Listening for incoming viewer connections on port %d.", thread_params->port); while(notstopped) { conn = socket_accept(thread_params->sock, (struct sockaddr *)&client, &socklen); if (conn == INVALID_SOCKET) { if (notstopped) logp(ERROR, "viewer_listen(): accept() failed, errno=%d", getLastErrNo()); } else { ip_addr = inet_ntoa(client.sin_addr); /* IP Address for monitoring purposes */ logp(INFO, "Viewer (socket=%d) connection accepted from %s.", conn, ip_addr); // Act like a server until the authentication phase is over. Send the protocol version. sprintf(protocol_version, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion); if( socket_send(conn, protocol_version, sz_rfbProtocolVersionMsg, "protocol version to viewer") ) { logp(DEBUG, "Protocol version sent to viewer (socket=%d).", conn); // Read the protocol version the client suggests (Must be 3.3) if( socket_recv(conn, protocol_version, sz_rfbProtocolVersionMsg, "protocol version from viewer") ) { logp(DEBUG, "Viewer (socket=%d) sent protocol version.", conn); // Send Authentication Type (VNC Authentication to keep it standard) auth_type = Swap32IfLE(rfbVncAuth); if( socket_send(conn, (char *)&auth_type, sizeof(auth_type), "auth type to viewer") ) { logp(DEBUG, "Authentication scheme sent to viewer (socket=%d).", conn); // We must send the 16 bytes challenge key. In order for this to work the challenge must be always the same. if( socket_send(conn, (char *)challenge_key, CHALLENGESIZE, "challenge key to viewer") ) { logp(DEBUG, "Challenge sent to viewer (socket=%d).", conn); // Read the password. It will be treated as the repeater IDentifier. memset(challenge, 0, CHALLENGESIZE); if( socket_recv(conn, (char *)challenge, CHALLENGESIZE, "challenge response from viewer") ) { logp(DEBUG, "Viewer (socket=%d) sent challenge response.", conn); // Send Authentication response auth_response = Swap32IfLE(rfbVncAuthOK); if( socket_send(conn, (char *)&auth_response, sizeof(auth_response), "auth response to viewer") ) { logp(DEBUG, "Authentication response sent to viewer (socket=%d).", conn); // Retrieve ClientInit and save it inside the structure. if( socket_recv(conn, (char *)&client_init, sizeof(client_init), "ClientInit from viewer") ) { logp(DEBUG, "Viewer (socket=%d) sent ClientInit message.", conn); add_new_slot(INVALID_SOCKET, conn, challenge, -1); } } } } } } } } } notstopped = false; socket_close(thread_params->sock); log(INFO, "Viewer listening thread has exited."); return 0; }
THREAD_CALL server_listen(LPVOID lpParam) { listener_thread_params *thread_params = (listener_thread_params *)lpParam; SOCKET conn; struct sockaddr_in client; socklen_t socklen = sizeof(client); rfbProtocolVersionMsg protocol_version; char host_id[MAX_HOST_NAME_LEN + 1]; char phost[MAX_HOST_NAME_LEN + 1]; CARD32 auth_type; unsigned char challenge[CHALLENGESIZE]; uint32_t code; char *ip_addr; thread_params->sock = create_listener_socket( thread_params->port ); if (thread_params->sock == INVALID_SOCKET) notstopped = false; else logp(DEBUG, "Listening for incoming server connections on port %d.", thread_params->port); while(notstopped) { conn = socket_accept(thread_params->sock, (struct sockaddr *)&client, &socklen); if (conn == INVALID_SOCKET) { if (notstopped) logp(ERROR, "server_listen(): accept() failed, errno=%d", getLastErrNo()); } else { ip_addr = inet_ntoa(client.sin_addr); /* IP Address for monitoring purposes */ logp(INFO, "Server (socket=%d) connection accepted from %s.", conn, ip_addr); // First thing is first: Get the repeater ID... if( socket_recv(conn, host_id, MAX_HOST_NAME_LEN, "hostid from server") ) { // Check and cypher the ID if( ParseDisplay(host_id, phost, MAX_HOST_NAME_LEN, (int *)&code, challenge) ) { logp(DEBUG, "Server (socket=%d) sent the host ID:%d.", conn, code); // Continue with the handshake until ClientInit. Read the Protocol Version. if( socket_recv(conn, protocol_version, sz_rfbProtocolVersionMsg, "protocol version from server") ) { // ToDo: Make sure the version is OK! logp(DEBUG, "Server (socket=%d) sent protocol version.", conn); // Tell the server we are using Protocol Version 3.3 sprintf(protocol_version, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion); if( socket_send(conn, protocol_version, sz_rfbProtocolVersionMsg, "protocol version to server") ) { logp(DEBUG, "Protocol version sent to server (socket=%d).", conn); // The server should send the authentication type it whises to use. // ToDo: We could add a password this would restrict other servers from connecting to our repeater, // in the meanwhile, assume no auth is the only scheme allowed. if( socket_recv(conn, (char *)&auth_type, sizeof(auth_type), "auth type from server") ) { logp(DEBUG, "Server (socket=%d) sent authentication scheme.", conn); if( Swap32IfLE(auth_type) != rfbNoAuth ) { logp(ERROR, "Invalid authentication scheme sent by server (socket=%d).", conn); socket_close(conn); } else add_new_slot(conn, INVALID_SOCKET, challenge, code); } } } } else logp(ERROR, "server_listen(): Reading Proxy settings error %s", host_id); } } } notstopped = false; socket_close(thread_params->sock); log(INFO, "Server listening thread has exited.\n"); return 0; }