Ejemplo n.º 1
0
function websocket_send_all(&$websocket, $data)
{
    websocket_send_others($websocket, 0, $data);
}
Ejemplo n.º 2
0
function handle_message(&$websocket, $client, $message)
{
    global $database;
    global $client_names;
    global $client_numbers;
    global $fragments;
    echo "{$client} |==> {$message} <==|\n";
    if ($message[0] == '?') {
        $resp = file_get_contents("test.dat");
        websocket_send($websocket, $client, '!');
        websocket_send($websocket, $client, $resp);
        return;
    }
    if ($message[0] == "-") {
        if (!array_key_exists($client, $fragments)) {
            $fragments[$client] = "";
        }
        $fragments[$client] .= substr($message, 1);
        websocket_send($websocket, $client, "&");
        return;
    } else {
        if ($message[0] == "%") {
            if (array_key_exists($client, $fragments) && $fragments[$client] != "") {
                websocket_send($websocket, $client, "&");
            }
            return;
        } else {
            if ($message[0] == "+") {
                if (array_key_exists($client, $fragments) && $fragments[$client] != "") {
                    $message = $fragments[$client] . substr($message, 1);
                    $fragments[$client] = "";
                } else {
                    $message = substr($message, 1);
                }
            }
        }
    }
    $args = NULL;
    $action = NULL;
    $name = NULL;
    $data = NULL;
    $links = NULL;
    $assets = NULL;
    $asset = NULL;
    $error = NULL;
    $ans = NULL;
    $res = NULL;
    $clients = NULL;
    if ($message[0] != '{') {
        $error = 'an object expected';
        $args = array();
    } else {
        $args = json_decode($message, true);
        if (!$args) {
            $error = 'JSON error ' . json_last_error() . ': ' . json_last_error_msg();
            $args = array();
        }
    }
    if (isset($args['action'])) {
        $action = $args['action'];
    } else {
        if (!$error) {
            $error = 'no "action" property specified';
        }
    }
    if (isset($args['client'])) {
        $name = $args['client'];
    }
    if (!$error && isset($args['data'])) {
        $data = $args['data'];
        if (!is_array($data)) {
            $error = 'property "data" is not an object';
        } else {
            if (!$name && isset($data['client'])) {
                $name = $data['client'];
            }
            if (isset($data['connections'])) {
                $links = array();
                foreach ($data['connections'] as $other) {
                    $links[$other] = TRUE;
                }
                unset($data['connections']);
            }
            if (isset($data['assets'])) {
                $assets = array();
                foreach ($data['assets'] as $asset) {
                    $assets[$asset] = TRUE;
                }
                unset($data['assets']);
            }
        }
    }
    if (isset($args['asset'])) {
        $asset = $args['asset'];
    }
    if ($error) {
        // error, do nothing
    } else {
        if (!is_string($action)) {
            $error = 'action is not a string';
        } else {
            if ($action == 'set') {
                if (!$name) {
                    $error = 'no "client" specified';
                } else {
                    $query = "";
                    $result = FALSE;
                    $esc_name = escape_literal($name);
                    if (isset($links)) {
                        $query = 'DELETE FROM links WHERE a = ' . $esc_name . ' OR b = ' . $esc_name . ';';
                        $newlinks = "";
                        foreach ($links as $other => $val) {
                            $newlinks .= ', (' . $esc_name . ',' . escape_literal($other) . ')';
                        }
                        if ($newlinks != "") {
                            $query .= 'INSERT INTO links (a, b) VALUES' . substr($newlinks, 1) . ';';
                        }
                        $result = pg_query($database, $query);
                        if ($result === FALSE) {
                            $error = pg_last_error($database);
                        }
                    }
                    if ($data && !$error) {
                        $query = '';
                        foreach ($data as $key => $val) {
                            $query .= ', ' . pg_escape_identifier($key) . ' = ' . escape_literal($val);
                        }
                        if (strlen($query) > 1) {
                            $query = 'UPDATE clients SET' . substr($query, 1) . ' WHERE client = ' . escape_literal($name) . ';';
                            $result = pg_query($database, $query);
                            if (!$result) {
                                $error = pg_last_error($database);
                            } else {
                                if (pg_affected_rows($result) < 1) {
                                    $result = FALSE;
                                }
                            }
                        }
                    }
                    if (!$error && !$result) {
                        if ($name) {
                            if (!$data) {
                                $data = array('client' => $name);
                            } else {
                                if (!isset($data['client'])) {
                                    $data['client'] = $name;
                                }
                            }
                        }
                        if (isset($data['client'])) {
                            $keys = '';
                            $vals = '';
                            foreach ($data as $key => $val) {
                                $keys .= ', ' . pg_escape_identifier($key);
                                $vals .= ', ' . escape_literal($val);
                            }
                            $query = 'INSERT INTO clients (' . substr($keys, 2) . ') VALUES (' . substr($vals, 2) . ');';
                            $result = pg_query($database, $query);
                            if (!$result) {
                                $error = pg_last_error($database);
                            }
                        }
                    }
                }
            } else {
                if ($action == 'get') {
                    if ($name) {
                        if (!isset($data['client'])) {
                            $data['client'] = $name;
                        } else {
                            if ($data['client'] != $name) {
                                $error = 'two clients specified';
                            }
                        }
                    }
                    $res = NULL;
                    if (!$error) {
                        $filter = '';
                        if (!empty($data)) {
                            foreach ($data as $key => $val) {
                                $filter .= ' AND ' . pg_escape_identifier($database, $key) . ' = ' . escape_literal($val);
                            }
                            $filter = ' WHERE' . substr($filter, 4);
                        }
                        $query = 'SELECT * FROM clients' . $filter . ';';
                        $result = pg_query($database, $query);
                        if ($result === FALSE) {
                            $error = pg_last_error($database);
                        } else {
                            $res = pg_fetch_all($result);
                            pg_free_result($result);
                        }
                    }
                    if (!$res) {
                        $res = array();
                    }
                    if (!$error) {
                        $result = pg_query($database, 'SELECT * FROM links;');
                        if ($result === FALSE) {
                            $error = pg_last_error($database);
                        } else {
                            $links = pg_fetch_all($result);
                            pg_free_result($result);
                            $m = count($res);
                            $n = count($links);
                            for ($i = 0; $i < $m; $i++) {
                                $name_i = $res[$i]['client'];
                                $links_i = array();
                                for ($j = 0; $j < $n; $j++) {
                                    if ($links[$j]['a'] == $name_i) {
                                        $links_i[$links[$j]['b']] = 1;
                                    } else {
                                        if ($links[$j]['b'] == $name_i) {
                                            $links_i[$links[$j]['a']] = 1;
                                        }
                                    }
                                }
                                $res[$i]['connections'] = array_keys($links_i);
                            }
                        }
                    }
                    if (!$error) {
                        $query = 'SELECT * FROM assets';
                        if ($name) {
                            $query .= ' WHERE "client" = ' . escape_literal($name);
                        }
                        $result = pg_query($database, $query);
                        $assets = array();
                        $n = pg_num_rows($result);
                        for ($i = 0; $i < $n; $i++) {
                            $name_i = pg_fetch_result($result, $i, 'client');
                            $asset_i = pg_fetch_result($result, $i, 'asset');
                            if (!isset($assets[$name_i])) {
                                $assets[$name_i] = array();
                            }
                            $assets[$name_i][] = $asset_i;
                        }
                        $n = count($res);
                        for ($i = 0; $i < $n; $i++) {
                            $name_i = $res[$i]['client'];
                            if (isset($assets[$name_i])) {
                                $res[$i]['assets'] = $assets[$name_i];
                            } else {
                                $res[$i]['assets'] = array();
                            }
                        }
                    }
                } else {
                    if ($action == 'ask_asset') {
                        $logmsg = NULL;
                        $settings = get_settings();
                        $random = TRUE;
                        foreach ($settings as $setting) {
                            if ($setting['key'] == 'random') {
                                $val = $setting['value'];
                                $random = $val[0] != 'F' && $val[0] != 'f';
                            }
                        }
                        $clients = array();
                        $info = NULL;
                        $result = pg_query($database, 'SELECT * FROM clients;');
                        if ($result === FALSE) {
                            $error = pg_last_error($database);
                        } else {
                            $info = pg_fetch_all($result);
                            pg_free_result($result);
                            $m = count($info);
                            $query = 'SELECT * FROM links;';
                            $result = pg_query($database, $query);
                            if ($result === FALSE) {
                                $error = pg_last_error($database);
                            } else {
                                $links = pg_fetch_all($result);
                                pg_free_result($result);
                                $n = count($links);
                                $my_i = -1;
                                $weights = get_algorithm_weights();
                                use_algorithm_weights($weights);
                                for ($i = 0; $i < $m; $i++) {
                                    $name_i = $info[$i]['client'];
                                    if ($name_i == $name) {
                                        $my_i = $i;
                                    }
                                    $links_i = array();
                                    for ($j = 0; $j < $n; $j++) {
                                        if ($links[$j]['a'] == $name_i) {
                                            $links_i[$links[$j]['b']] = 1;
                                        } else {
                                            if ($links[$j]['b'] == $name_i) {
                                                $links_i[$links[$j]['a']] = 1;
                                            }
                                        }
                                    }
                                    $info[$i]['connections'] = array_keys($links_i);
                                }
                                if ($my_i >= 0) {
                                    $scores = array();
                                    for ($i = 0; $i < $m; $i++) {
                                        $info_i = $info[$i];
                                        if ($i != $my_i && isset($client_numbers[$info_i['client']])) {
                                            if ($random) {
                                                $score_i = mt_rand(0, mt_getrandmax());
                                            } else {
                                                $score_i = score($info[$my_i], $info_i);
                                            }
                                            if ($score_i >= 0) {
                                                $scores[$info_i['client']] = $score_i;
                                            }
                                        }
                                    }
                                    arsort($scores);
                                    $clients = array_keys($scores);
                                }
                                if ($random) {
                                    $logmsg = "asset source random selection";
                                } else {
                                    $logmsg = "asset source selection";
                                }
                            }
                        }
                        if ($logmsg != NULL) {
                            $n = count($clients);
                            if ($n > 5) {
                                $clients = array_slice($clients, 0, 5);
                            }
                            $n = count($clients);
                            $log_data = array();
                            $log_data['client'] = $name;
                            $log_data['weights'] = $weights;
                            if ($n > 0) {
                                $sum_battery = 0;
                                $sum_speed = 0;
                                for ($i = 0; $i < $m; $i++) {
                                    if (array_search($info[$i]['client'], $clients) !== FALSE) {
                                        if ($info[$i]['battery_charging'][0] == 't') {
                                            $sum_battery += 100;
                                        } else {
                                            $sum_battery += $info[$i]['battery_level'];
                                        }
                                        $sum_speed += $info[$i]['client_processing_speed'];
                                    }
                                }
                                $log_data['avg_battery'] = number_format($sum_battery / $n, 0, '.', '');
                                $log_data['avg_speed'] = number_format($sum_speed / $n, 1, '.', '');
                            }
                            $log_data['peers'] = $clients;
                            log_message($name, $logmsg, $log_data);
                        }
                    } else {
                        if ($action == 'delete') {
                            if (!isset($name)) {
                                $error = 'no "client" property';
                            } else {
                                if (isset($data)) {
                                    $error = 'extraneous "data" property';
                                } else {
                                    $esc_name = escape_literal($name);
                                    $query = 'DELETE FROM clients WHERE client = ' . $esc_name . ';';
                                    $result = pg_query($database, $query);
                                    if ($result === FALSE) {
                                        $error = pg_last_error($database);
                                    } else {
                                        if (pg_affected_rows($result) < 1) {
                                            $error = 'client ' . $args['client'] . ' not found';
                                        }
                                        pg_free_result($result);
                                    }
                                    $query = 'DELETE FROM links WHERE a = ' . $esc_name . ' OR b = ' . $esc_name . ';';
                                    $result = pg_query($database, $query);
                                    if ($result === FALSE) {
                                        $error = pg_last_error($database);
                                    }
                                }
                            }
                        } else {
                            if ($action == 'clear') {
                                if (isset($name)) {
                                    $error = 'extraneous "client" property';
                                } else {
                                    if (isset($data)) {
                                        $error = 'extraneous "data" property';
                                    } else {
                                        $result = pg_query($database, 'DELETE FROM clients;');
                                        if ($result === FALSE) {
                                            $error = pg_last_error($database);
                                        } else {
                                            $ans = pg_affected_rows($result);
                                            pg_free_result($result);
                                        }
                                        pg_query($database, "VACUUM FULL clients;");
                                    }
                                }
                            } else {
                                if ($action == 'name') {
                                    if (isset($name)) {
                                        set_client($client, $name);
                                    } else {
                                        $ans = NULL;
                                        $guess = -1;
                                        while ($ans == NULL) {
                                            if ($guess < 0) {
                                                if (isset($client_names[$client])) {
                                                    $ans = $client_names[$client];
                                                }
                                            } else {
                                                if ($guess == 0) {
                                                    $ans = 'client_' . $client;
                                                } else {
                                                    $letter = chr(0x61 + ($guess - 1) % 26);
                                                    $num = ($guess - 1) / 26;
                                                    $ans = 'client_' . $client . $letter . ($num > 0 ? $num : '');
                                                    if (isset($client_numbers[$ans])) {
                                                        if ($client_numbers[$ans] != $client) {
                                                            $ans = NULL;
                                                        }
                                                    }
                                                }
                                            }
                                            $guess++;
                                        }
                                    }
                                } else {
                                    if ($action == 'version') {
                                        $ans = date("Y-m-d G:i:s", filemtime("Server.php"));
                                    } else {
                                        if ($action == 'log') {
                                            log_message($name, $args['message'], $data);
                                        } else {
                                            if ($action == 'clear_log') {
                                                $text = date("Y-m-d G:i:s") . "\n";
                                                $text .= "========================================\n";
                                                file_put_contents("Server_log.txt", $text, LOCK_EX);
                                            } else {
                                                if ($action == 'say') {
                                                    if (!isset($client_names[$client])) {
                                                        $error = 'Client name not set';
                                                    } else {
                                                        $msg = $args;
                                                        $msg['action'] = "said";
                                                        $msg['client'] = $client_names[$client];
                                                        $msge = json_encode($msg);
                                                        if (isset($name)) {
                                                            if (isset($client_numbers[$name])) {
                                                                websocket_send($websocket, $client_numbers[$name], $msge);
                                                            } else {
                                                                $error = 'Client "' . $name . '" not known';
                                                            }
                                                        } else {
                                                            websocket_send_others($websocket, $client, $msge);
                                                        }
                                                    }
                                                } else {
                                                    if ($action == 'terminate') {
                                                        websocket_shutdown($websocket);
                                                        // after response is sent
                                                    } else {
                                                        if ($action == 'nop') {
                                                            // no action
                                                        } else {
                                                            $error = 'action ' . $action . ' not understood by server';
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $resp = array();
    if (isset($error)) {
        $resp['error'] = $error;
        console("<*> " + $error);
    }
    if (isset($action)) {
        $resp['action'] = $action;
    }
    if (isset($ans)) {
        $resp['ans'] = $ans;
    }
    if (isset($res)) {
        $resp['res'] = $res;
    }
    if (isset($asset)) {
        $resp['asset'] = $asset;
    }
    if (isset($clients)) {
        $resp['clients'] = $clients;
    }
    $resp = json_encode($resp);
    websocket_send($websocket, $client, $resp);
}