<? class socket { var $address = "0.0.0.0"; var $port = 4000; var $client = array(); var $read = array(); var $listen_fd; var $nready; function socket( $address, $port ) { set_time_limit(0); ob_implicit_flush(); $this->address = $address; $this->port = $port; $this->socket_init(); } function resetconnection ( $desc, $indx ) { remove_player( $indx ); $this->client[$indx] = NULL; echo "Just dropped : $desc with an index of $indx\n"; $this->read[$indx] = NULL; $this->close( $desc ); } function socket_init() { if( ( $this->listen_fd = socket_create(AF_INET, SOCK_STREAM, 0) ) < 0 ) { echo "socket_create() failed: reason: " . socket_strerror ($ret) . "\n"; exit; } socket_setopt( $this->listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); if( ( $ret = socket_bind($this->listen_fd, $this->address, $this->port)) < 0 ) { echo "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n"; $this->close( $this->listen_fd ); exit; } if( ( $ret = socket_listen( $this->listen_fd ) ) < 0 ) { echo "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n"; exit; } echo "Scratch mud up and running at: $this->address:$this->port\n"; } function close( $sock ) { socket_close( $sock ); } function first_time ( $desc, $indx ) { if ( !$this->client[$indx]["already_playing"] ) { return true; } else if ( empty( $desc ) ) { $this->resetconnection( $desc, $indx ); return false; } else return false; } function show_header ( $desc, $indx, $n ) { if( empty( $n ) || strlen( $n ) < 5 ) { send_to_desc( $desc, "You're name must be greater than 5 characters\n" ); send_to_desc( $desc, "What is your name?: "); $input = trim(socket_read($desc, 1024)); $this->show_header( $desc, $indx, $input ); } else if ( $desc ) { $player = new Player; $player->name = $n; $player->prompt = " bar>"; $player->sock_id = $desc; $player->con = CON_CONNECTING; /* add the player to the world char_list array for quick global reference */ add_player( $indx, $player ); socket_getpeername ($desc, $peer_addr, $peer_port); game_log( " Connection from $peer_addr\n\r" ); bust_a_prompt( $player ); $this->client[$indx]["already_playing"] = true; } else { $this->resetconnection( $desc, $indx ); game_log( "[Bug] => resetting connection for $desc with index of => $indx\n"); } } function recv() { global $char_list; for( $i = 0; $i < MAX_CLIENTS; $i++ ) { $desc = $this->client[$i][0]; if ( in_array( $desc, $this->read ) ) { //There has to be a better way to check for closing sockets if( ( $ret = @socket_getpeername ($desc, $peer_addr, $peer_port) ) <= 0 ) { $this->resetconnection( $desc, $i ); break; } $n = trim(socket_read($desc, 1024)); if( $this->first_time( $desc, $i ) ) { $this->show_header( $desc, $i, $n ); break; } if ($n) { $tokens = array(); $raw_tokens = explode (' ', trim ($n)); //the first one is the command $command = $raw_tokens[0]; if( ( $ret_arr = check_command( $command ) ) > 0 ) { $params = array_slice ($raw_tokens, 1); //store them to pass them to the command parser $ret_command = $ret_arr[0]; //It'll be better to move this to it's own wrapper //for a more detailed command parser $ret_command( $char_list[$i], $params ); } else { socket_write($desc, "Huh? [ $command ]\n"); } bust_a_prompt( $char_list[$i] ); } } } } function accept_new_connection() { global $char_list; $this->read[0] = $this->listen_fd; // these next lines set up our clients and our // listener socket for reading... for( $i = 0; $i < MAX_CLIENTS; $i++ ) { /* If they are already connected, put them back in * the read[] array since we just wiped it */ if( $this->client[$i][0] != NULL ) { $this->read[$i + 1] = $this->client[$i][0]; } } // now a blocking call to socket_select(). This will // wait forever until a connection is received. $nready = socket_select( $this->read, $null, $null, null); // if a new connection is being made, accept it and // put it into the client array... if ( in_array( $this->listen_fd, $this->read) ) { for ($i = 0; $i < MAX_CLIENTS; $i++) { if ($this->client[$i][0] == null) { $this->client[$i][0] = socket_accept( $this->listen_fd ); if ( !$this->client[$i]["already_playing"] ) { socket_write($this->client[$i][0], "This is the welcome, enter name: "); } //socket already established but closed break; } else if ($i == MAX_CLIENTS - 1) trigger_error("too many clients", E_USER_ERROR); if (--$nready <= 0) { continue; } } } } };