commit
60377f2262
@ -0,0 +1,10 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
AILog.Info("1.5 API compatibility in effect.");
|
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
@ -0,0 +1,216 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
class Regression extends AIController {
|
||||||
|
function Start();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function Regression::StationList()
|
||||||
|
{
|
||||||
|
local list = AIStationList(AIStation.STATION_BUS_STOP + AIStation.STATION_TRUCK_STOP);
|
||||||
|
|
||||||
|
print("");
|
||||||
|
print("--StationList--");
|
||||||
|
print(" Count(): " + list.Count());
|
||||||
|
list.Valuate(AIStation.GetLocation);
|
||||||
|
print(" Location ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetCargoWaiting, 0);
|
||||||
|
print(" CargoWaiting(0) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetCargoWaiting, 1);
|
||||||
|
print(" CargoWaiting(1) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_Cargo()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_Cargo--");
|
||||||
|
|
||||||
|
for (local mode = AIStationList_Cargo.CM_WAITING; mode <= AIStationList_Cargo.CM_PLANNED; ++mode) {
|
||||||
|
print(" " + mode);
|
||||||
|
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA ; ++selector) {
|
||||||
|
print(" " + selector);
|
||||||
|
local list = AIStationList_Cargo(mode, selector, 6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoPlanned()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoPlanned--");
|
||||||
|
|
||||||
|
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
|
||||||
|
print(" " + selector);
|
||||||
|
local list = AIStationList_CargoPlanned(selector, 6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoPlannedByFrom()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoPlannedByFrom--");
|
||||||
|
local list = AIStationList_CargoPlannedByFrom(2, 0);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoPlannedByVia()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoPlannedByVia--");
|
||||||
|
local list = AIStationList_CargoPlannedByVia(2, 0);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoPlannedViaByFrom()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoPlannedViaByFrom--");
|
||||||
|
local list = AIStationList_CargoPlannedViaByFrom(6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoPlannedFromByVia()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoPlannedFromByVia--");
|
||||||
|
local list = AIStationList_CargoPlannedFromByVia(6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoWaiting()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoWaiting--");
|
||||||
|
|
||||||
|
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
|
||||||
|
print(" " + selector);
|
||||||
|
local list = AIStationList_CargoWaiting(selector, 6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoWaitingByFrom()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoWaitingByFrom--");
|
||||||
|
local list = AIStationList_CargoWaitingByFrom(2, 0);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoWaitingByVia()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoWaitingByVia--");
|
||||||
|
local list = AIStationList_CargoWaitingByVia(2, 0);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoWaitingViaByFrom()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoWaitingViaByFrom--");
|
||||||
|
local list = AIStationList_CargoWaitingViaByFrom(6, 0, 7);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_CargoWaitingFromByVia()
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
print("--StationList_CargoWaitingFromByVia--");
|
||||||
|
local list = AIStationList_CargoWaitingFromByVia(2, 0, 2);
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function Regression::StationList_Vehicle()
|
||||||
|
{
|
||||||
|
local list = AIStationList_Vehicle(12);
|
||||||
|
|
||||||
|
print("");
|
||||||
|
print("--StationList_Vehicle--");
|
||||||
|
print(" Count(): " + list.Count());
|
||||||
|
list.Valuate(AIStation.GetLocation);
|
||||||
|
print(" Location ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetCargoWaiting, 0);
|
||||||
|
print(" CargoWaiting(0) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetCargoWaiting, 1);
|
||||||
|
print(" CargoWaiting(1) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetCargoRating, 1);
|
||||||
|
print(" CargoRating(1) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetDistanceManhattanToTile, 30000);
|
||||||
|
print(" DistanceManhattanToTile(30000) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.GetDistanceSquareToTile, 30000);
|
||||||
|
print(" DistanceSquareToTile(30000) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
list.Valuate(AIStation.IsWithinTownInfluence, 0);
|
||||||
|
print(" IsWithinTownInfluence(0) ListDump:");
|
||||||
|
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
|
||||||
|
print(" " + i + " => " + list.GetValue(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Regression::Start()
|
||||||
|
{
|
||||||
|
StationList();
|
||||||
|
StationList_Cargo();
|
||||||
|
StationList_CargoPlanned();
|
||||||
|
StationList_CargoPlannedByFrom();
|
||||||
|
StationList_CargoPlannedByVia();
|
||||||
|
StationList_CargoPlannedViaByFrom();
|
||||||
|
StationList_CargoPlannedFromByVia();
|
||||||
|
StationList_CargoWaiting();
|
||||||
|
StationList_CargoWaitingByFrom();
|
||||||
|
StationList_CargoWaitingByVia();
|
||||||
|
StationList_CargoWaitingViaByFrom();
|
||||||
|
StationList_CargoWaitingFromByVia();
|
||||||
|
StationList_Vehicle();
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
--StationList--
|
||||||
|
Count(): 5
|
||||||
|
Location ListDump:
|
||||||
|
6 => 42341
|
||||||
|
2 => 41831
|
||||||
|
7 => 41825
|
||||||
|
5 => 33421
|
||||||
|
4 => 33411
|
||||||
|
CargoWaiting(0) ListDump:
|
||||||
|
7 => 6
|
||||||
|
6 => 6
|
||||||
|
2 => 3
|
||||||
|
5 => 0
|
||||||
|
4 => 0
|
||||||
|
CargoWaiting(1) ListDump:
|
||||||
|
7 => 0
|
||||||
|
6 => 0
|
||||||
|
5 => 0
|
||||||
|
4 => 0
|
||||||
|
2 => 0
|
||||||
|
|
||||||
|
--StationList_Cargo--
|
||||||
|
0
|
||||||
|
0
|
||||||
|
6 => 6
|
||||||
|
1
|
||||||
|
6 => 2
|
||||||
|
2
|
||||||
|
2 => 4
|
||||||
|
7 => 2
|
||||||
|
3
|
||||||
|
1
|
||||||
|
0
|
||||||
|
7 => 18
|
||||||
|
6 => 16
|
||||||
|
2 => 7
|
||||||
|
1
|
||||||
|
6 => 8
|
||||||
|
2 => 3
|
||||||
|
2
|
||||||
|
2 => 16
|
||||||
|
6 => 14
|
||||||
|
7 => 11
|
||||||
|
3
|
||||||
|
6 => 10
|
||||||
|
2 => 8
|
||||||
|
|
||||||
|
--StationList_CargoPlanned--
|
||||||
|
0
|
||||||
|
7 => 18
|
||||||
|
6 => 16
|
||||||
|
2 => 7
|
||||||
|
1
|
||||||
|
6 => 8
|
||||||
|
2 => 3
|
||||||
|
2
|
||||||
|
2 => 16
|
||||||
|
6 => 14
|
||||||
|
7 => 11
|
||||||
|
3
|
||||||
|
6 => 10
|
||||||
|
2 => 8
|
||||||
|
|
||||||
|
--StationList_CargoPlannedByFrom--
|
||||||
|
7 => 8
|
||||||
|
6 => 8
|
||||||
|
2 => 7
|
||||||
|
|
||||||
|
--StationList_CargoPlannedByVia--
|
||||||
|
2 => 16
|
||||||
|
6 => 7
|
||||||
|
|
||||||
|
--StationList_CargoPlannedViaByFrom--
|
||||||
|
6 => 8
|
||||||
|
2 => 3
|
||||||
|
|
||||||
|
--StationList_CargoPlannedFromByVia--
|
||||||
|
6 => 10
|
||||||
|
2 => 8
|
||||||
|
|
||||||
|
--StationList_CargoWaiting--
|
||||||
|
0
|
||||||
|
6 => 6
|
||||||
|
1
|
||||||
|
6 => 2
|
||||||
|
2
|
||||||
|
2 => 4
|
||||||
|
7 => 2
|
||||||
|
3
|
||||||
|
|
||||||
|
--StationList_CargoWaitingByFrom--
|
||||||
|
2 => 3
|
||||||
|
|
||||||
|
--StationList_CargoWaitingByVia--
|
||||||
|
6 => 3
|
||||||
|
|
||||||
|
--StationList_CargoWaitingViaByFrom--
|
||||||
|
6 => 2
|
||||||
|
|
||||||
|
--StationList_CargoWaitingFromByVia--
|
||||||
|
6 => 3
|
||||||
|
|
||||||
|
--StationList_Vehicle--
|
||||||
|
Count(): 2
|
||||||
|
Location ListDump:
|
||||||
|
5 => 33421
|
||||||
|
4 => 33411
|
||||||
|
CargoWaiting(0) ListDump:
|
||||||
|
5 => 0
|
||||||
|
4 => 0
|
||||||
|
CargoWaiting(1) ListDump:
|
||||||
|
5 => 0
|
||||||
|
4 => 0
|
||||||
|
CargoRating(1) ListDump:
|
||||||
|
5 => -1
|
||||||
|
4 => -1
|
||||||
|
DistanceManhattanToTile(30000) ListDump:
|
||||||
|
5 => 106
|
||||||
|
4 => 96
|
||||||
|
DistanceSquareToTile(30000) ListDump:
|
||||||
|
5 => 8818
|
||||||
|
4 => 7058
|
||||||
|
IsWithinTownInfluence(0) ListDump:
|
||||||
|
5 => 0
|
||||||
|
4 => 0
|
||||||
|
ERROR: The script died unexpectedly.
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,10 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GSLog.Info("1.5 API compatibility in effect.");
|
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,268 @@
|
|||||||
|
Some explanations about Desyncs
|
||||||
|
Last updated: 2014-02-23
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Table of contents
|
||||||
|
-----------------
|
||||||
|
1.0) Desync theory
|
||||||
|
* 1.1) OpenTTD multiplayer architecture
|
||||||
|
* 1.2) What is a Desync and how is it detected
|
||||||
|
* 1.3) Typical causes of Desyncs
|
||||||
|
2.0) What to do in case of a Desync
|
||||||
|
* 2.1) Cache debugging
|
||||||
|
* 2.2) Desync recording
|
||||||
|
3.0) Evaluating the Desync records
|
||||||
|
* 3.1) Replaying
|
||||||
|
* 3.2) Evaluation the replay
|
||||||
|
* 3.3) Comparing savegames
|
||||||
|
|
||||||
|
|
||||||
|
1.1) OpenTTD multiplayer architecture
|
||||||
|
---- --------------------------------
|
||||||
|
OpenTTD has a huge gamestate, which changes all of the time.
|
||||||
|
The savegame contains the complete gamestate at a specific point
|
||||||
|
in time. But this state changes completely each tick: Vehicles move
|
||||||
|
and trees grow.
|
||||||
|
|
||||||
|
However, most of these changes in the gamestate are deterministic:
|
||||||
|
Without a player interfering a vehicle follows its orders always
|
||||||
|
in the same way, and trees always grow the same.
|
||||||
|
|
||||||
|
In OpenTTD multiplayer synchronisation works by creating a savegame
|
||||||
|
when clients join, and then transfering that savegame to the client,
|
||||||
|
so it has the complete gamestate at a fixed point in time.
|
||||||
|
|
||||||
|
Afterwards clients only receive 'commands', that is: Stuff which is
|
||||||
|
not predictable, like
|
||||||
|
- player actions
|
||||||
|
- AI actions
|
||||||
|
- GameScript actions
|
||||||
|
- Admin Port command
|
||||||
|
- rcon commands
|
||||||
|
- ...
|
||||||
|
|
||||||
|
These commands contain the information on how to execute the command,
|
||||||
|
and when to execute it. Time is measured in 'network frames'.
|
||||||
|
Mind that network frames to not match ingame time. Network frames
|
||||||
|
also run while the game is paused, to give a defined behaviour to
|
||||||
|
stuff that is executing while the game is paused.
|
||||||
|
|
||||||
|
The deterministic part of the gamestate is run by the clients on
|
||||||
|
their own. All they get from the server is the instruction to
|
||||||
|
run the gamestate up to a certain network time, which basically
|
||||||
|
says that there are no commands scheduled in that time.
|
||||||
|
|
||||||
|
When a client (which includes the server itself) wants to execute
|
||||||
|
a command (i.e. a non-predictable action), it does this by
|
||||||
|
- calling DoCommandP resp. DoCommandPInternal
|
||||||
|
- These functions first do a local test-run of the command to
|
||||||
|
check simple preconditions. (Just to give the client an
|
||||||
|
immediate response without bothering the server and waiting for
|
||||||
|
the response.) The test-run may not actually change the
|
||||||
|
gamestate, all changes must be discarded.
|
||||||
|
- If the local test-run succeeds the command is sent to the server.
|
||||||
|
- The server inserts the command into the command queue, which
|
||||||
|
assigns a network frame to the commands, i.e. when it shall be
|
||||||
|
executed on all clients.
|
||||||
|
- Enhanced with this specific timestamp, the command is send to all
|
||||||
|
clients, which execute the command simultaneously in the same
|
||||||
|
network frame in the same order.
|
||||||
|
|
||||||
|
1.2) What is a Desync and how is it detected
|
||||||
|
---- ---------------------------------------
|
||||||
|
In the ideal case all clients have the same gamestate as the server
|
||||||
|
and run in sync. That is, vehicle movement is the same on all
|
||||||
|
clients, and commands are executed the same everywhere and
|
||||||
|
have the same results.
|
||||||
|
|
||||||
|
When a Desync happens, it means that the gamestates on the clients
|
||||||
|
(including the server) are no longer the same. Just imagine
|
||||||
|
that a vehicle picks the left line instead of the right line at
|
||||||
|
a junction on one client.
|
||||||
|
|
||||||
|
The important thing here is, that noone notices when a Desync
|
||||||
|
occurs. The desync client will continue to simulate the gamestate
|
||||||
|
and execute commands from the server. Once the gamestate differs
|
||||||
|
it will increasingly spiral out of control: If a vehicle picks a
|
||||||
|
different route, it will arrive at a different time at a station,
|
||||||
|
which will load different cargo, which causes other vehicles to
|
||||||
|
load other stuff, which causes industries to notice different
|
||||||
|
servicing, which causes industries to change production, ...
|
||||||
|
the client could run all day in a different universe.
|
||||||
|
|
||||||
|
To limit how long a Desync can remain unnoticed, the server
|
||||||
|
transfers some checksums every now and then for the gamestate.
|
||||||
|
Currently this checksum is the state of the random number
|
||||||
|
generator of the game logic. A lot of things in OpenTTD depend
|
||||||
|
on the RNG, and if the gamestate differs, it is likely that the
|
||||||
|
RNG is called at different times, and the state differs when
|
||||||
|
checked.
|
||||||
|
|
||||||
|
The clients compare this 'checksum' with the checksum of their
|
||||||
|
own gamestate at the specific network frame. If they differ,
|
||||||
|
the client disconnects with a Desync error.
|
||||||
|
|
||||||
|
The important thing here is: The detection of the Desync is
|
||||||
|
only an ultimate failure detection. It does not give any
|
||||||
|
indication on when the Desync happened. The Desync may after
|
||||||
|
all have occurred long ago, and just did not affect the checksum
|
||||||
|
up to now. The checksum may have matched 10 times or more
|
||||||
|
since the Desync happend, and only now the Desync has spiraled
|
||||||
|
enough to finally affect the checksum. (There was once a desync
|
||||||
|
which was only noticed by the checksum after 20 game years.)
|
||||||
|
|
||||||
|
1.3) Typical causes of Desyncs
|
||||||
|
---- -------------------------
|
||||||
|
Desyncs can be caused by the following scenarios:
|
||||||
|
- The savegame does not describe the complete gamestate.
|
||||||
|
- Some information which affects the progression of the
|
||||||
|
gamestate is not saved in the savegame.
|
||||||
|
- Some information which affects the progression of the
|
||||||
|
gamestate is not loaded from the savegame.
|
||||||
|
This includes the case that something is not completely
|
||||||
|
reset before loading the savegame, so data from the
|
||||||
|
previous game is carried over to the new one.
|
||||||
|
- The gamestate does not behave deterministic.
|
||||||
|
- Cache mismatch: The game logic depends on some cached
|
||||||
|
values, which are not invalidated properly. This is
|
||||||
|
the usual case for NewGRF-specific Desyncs.
|
||||||
|
- Undefined behaviour: The game logic performs multiple
|
||||||
|
things in an undefined order or with an undefined
|
||||||
|
result. E.g. when sorting something with a key while
|
||||||
|
some keys are equal. Or some computation that depends
|
||||||
|
on the CPU architecture (32/64 bit, little/big endian).
|
||||||
|
- The gamestate is modified when it shall not be modified.
|
||||||
|
- The test-run of a command alters the gamestate.
|
||||||
|
- The gamestate is altered by a player or script without
|
||||||
|
using commands.
|
||||||
|
|
||||||
|
|
||||||
|
2.1) Cache debugging
|
||||||
|
---- ---------------
|
||||||
|
Desyncs which are caused by inproper cache validation can
|
||||||
|
often be found by enabling cache validation:
|
||||||
|
- Start OpenTTD with '-d desync=2'.
|
||||||
|
- This will enable validation of caches every tick.
|
||||||
|
That is, cached values are recomputed every tick and compared
|
||||||
|
to the cached value.
|
||||||
|
- Differences are logged to 'commands-out.log' in the autosave
|
||||||
|
folder.
|
||||||
|
|
||||||
|
Mind that this type of debugging can also be done in singleplayer.
|
||||||
|
|
||||||
|
2.2) Desync recording
|
||||||
|
---- ----------------
|
||||||
|
If you have a server, which happens to encounter Desyncs often,
|
||||||
|
you can enable recording of the gamestate alterations. This
|
||||||
|
will later allow the replay the gamestate and locate the Desync
|
||||||
|
cause.
|
||||||
|
|
||||||
|
There are two levels of Desync recording, which are enabled
|
||||||
|
via '-d desync=2' resp. '-d desync=3'. Both will record all
|
||||||
|
commands to a file 'commands-out.log' in the autosave folder.
|
||||||
|
|
||||||
|
If you have the savegame from the start of the server, and
|
||||||
|
this command log you can replay the whole game. (see Section 3.1)
|
||||||
|
|
||||||
|
If you do not start the server from a savegame, there will
|
||||||
|
also be a savegame created just after a map has been generated.
|
||||||
|
The savegame will be named 'dmp_cmds_*.sav' and be put into
|
||||||
|
the autosave folder.
|
||||||
|
|
||||||
|
In addition to that '-d desync=3' also creates regular savegames
|
||||||
|
at defined spots in network time. (more defined than regular
|
||||||
|
autosaves). These will be created in the autosave folder
|
||||||
|
and will also be named 'dmp_cmds_*.sav'.
|
||||||
|
|
||||||
|
These saves allow comparing the gamestate with the original
|
||||||
|
gamestate during replaying, and thus greatly help debugging.
|
||||||
|
However, they also take a lot of disk space.
|
||||||
|
|
||||||
|
|
||||||
|
3.1) Replaying
|
||||||
|
---- ---------
|
||||||
|
To replay a Desync recording, you need these files:
|
||||||
|
- The savegame from when the server was started, resp.
|
||||||
|
the automatically created savegame from when the map
|
||||||
|
was generated.
|
||||||
|
- The 'commands-out.log' file.
|
||||||
|
- Optionally the 'dmp_cmds_*.sav'.
|
||||||
|
Put these files into a safe spot. (Not your autosave folder!)
|
||||||
|
|
||||||
|
Next, prepare your OpenTTD for replaying:
|
||||||
|
- Get the same version of OpenTTD as the original server was running.
|
||||||
|
- Uncomment/enable the define 'DEBUG_DUMP_COMMANDS' in
|
||||||
|
'src/network/network_func.h'.
|
||||||
|
(DEBUG_FAILED_DUMP_COMMANDS is explained later)
|
||||||
|
- Put the 'commands-out.log' into the root save folder, and rename
|
||||||
|
it to 'commands.log'.
|
||||||
|
- Run 'openttd -D -d desync=3 -g startsavegame.sav'.
|
||||||
|
This replays the server log and creates new 'commands-out.log'
|
||||||
|
and 'dmp_cmds_*.sav' in your autosave folder.
|
||||||
|
|
||||||
|
3.2) Evaluation the replay
|
||||||
|
---- ---------------------
|
||||||
|
The replaying will also compare the checksums which are part of
|
||||||
|
the 'commands-out.log' with the replayed gamestate.
|
||||||
|
If they differ, it will trigger a 'NOT_REACHED'.
|
||||||
|
|
||||||
|
If the replay succeeds without mismatch, that is the replay reproduces
|
||||||
|
the original server state:
|
||||||
|
- Repeat the replay starting from incrementally later 'dmp_cmds_*.sav'
|
||||||
|
while truncating the 'commands.log' at the beginning appropriately.
|
||||||
|
The 'dmp_cmds_*.sav' can be your own ones from the first reply, or
|
||||||
|
the ones from the original server (if you have them).
|
||||||
|
(This simulates the view of joining clients during the game.)
|
||||||
|
- If one of those replays fails, you have located the Desync between
|
||||||
|
the last dmp_cmds that reproduces the replay and the first one
|
||||||
|
that fails.
|
||||||
|
|
||||||
|
If the replay does not succeed without mismatch, you can check the logs
|
||||||
|
whether there were failed commands. Then you may try to replay with
|
||||||
|
DEBUG_FAILED_DUMP_COMMANDS enabled. If the replay then fails, the
|
||||||
|
command test-run of the failed command modified the game state.
|
||||||
|
|
||||||
|
If you have the original 'dmp_cmds_*.sav', you can also compare those
|
||||||
|
savegames with your own ones from the replay. You can also comment/disable
|
||||||
|
the 'NOT_REACHED' mentioned above, to get another 'dmp_cmds_*.sav' from
|
||||||
|
the replay after the mismatch has already been detected.
|
||||||
|
See Section 3.2 on how to compare savegames.
|
||||||
|
If the saves differ you have located the Desync between the last dmp_cmds
|
||||||
|
that match and the first one that does not. The difference of the saves
|
||||||
|
may point you in the direction of what causes it.
|
||||||
|
|
||||||
|
If the replay succeeds without mismatch, and you do not have any
|
||||||
|
'dmp_cmd_*.sav' from the original server, it is a lost case.
|
||||||
|
Enable creation of the 'dmp_cmd_*.sav' on the server, and wait for the
|
||||||
|
next Desync.
|
||||||
|
|
||||||
|
Finally, you can also compare the 'commands-out.log' from the original
|
||||||
|
server with the one from the replay. They will differ in stuff like
|
||||||
|
dates, and the original log will contain the chat, but otherwise they
|
||||||
|
should match.
|
||||||
|
|
||||||
|
3.2) Comparing savegames
|
||||||
|
---- -------------------
|
||||||
|
The binary form of the savegames from the original server and from
|
||||||
|
your replay will always differ:
|
||||||
|
- The savegame contains paths to used NewGRF files.
|
||||||
|
- The gamelog will log your loading of the savegame.
|
||||||
|
- The savegame data of AIs and the Gamescript will differ.
|
||||||
|
Scripts are not run during the replay, only their recorded commands
|
||||||
|
are replayed. Their internal state will thus not change in the
|
||||||
|
replay and will differ.
|
||||||
|
|
||||||
|
To compare savegame more semantically, there exist some ugly hackish
|
||||||
|
tools at:
|
||||||
|
http://devs.openttd.org/~frosch/texts/zpipe.c
|
||||||
|
http://devs.openttd.org/~frosch/texts/printhunk.c
|
||||||
|
|
||||||
|
The first one decompresses OpenTTD savegames. The second one creates
|
||||||
|
a textual representation of an uncompressed savegame, by parsing hunks
|
||||||
|
and arrays and such. With both tools you need to be a bit careful
|
||||||
|
since they work on stdin and stdout, which may not deal well with
|
||||||
|
binary data.
|
||||||
|
|
||||||
|
If you have the textual representation of the savegames, you can
|
||||||
|
compare them with regular diff tools.
|
@ -0,0 +1,32 @@
|
|||||||
|
# $Id$
|
||||||
|
|
||||||
|
# This file is part of OpenTTD.
|
||||||
|
# OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
# OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
# Very basic variant function; barely any error checking.
|
||||||
|
# Just use the first argument as the file to start from when assembling everything
|
||||||
|
path = ARGV[1];
|
||||||
|
gsub("[^/\\\\]*$", "", path);
|
||||||
|
assemble(ARGV[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Recursive function for assembling by means of resolving the #includes.
|
||||||
|
function assemble(filename) {
|
||||||
|
while ((getline < filename) > 0) {
|
||||||
|
if (NF == 2 && $1 == "#include" ) {
|
||||||
|
# Remove the quotes.
|
||||||
|
gsub("[\"'<>]", "", $2);
|
||||||
|
assemble(path $2);
|
||||||
|
} else {
|
||||||
|
print $0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(filename) < 0) {
|
||||||
|
print "Could not open " filename > "/dev/stderr";
|
||||||
|
exit -1;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// This file is part of OpenTTD.
|
||||||
|
// OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
// OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
-1 * 0 0C "All black palette"
|
||||||
|
-1 * 0 05 18 01
|
||||||
|
-1 * 0 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
|
||||||
|
01
|
@ -1,77 +1,106 @@
|
|||||||
This package was debianized by Matthijs Kooijman <matthijs@stdin.nl>
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
on Wed, 15 Sep 2004 00:24:01 +0200.
|
Upstream-Name: OpenTTD
|
||||||
|
Upstream-Contact: info@openttd.org, #openttd on irc.oftc.net
|
||||||
Upstream author: Ludvig Strigeus (ludde) and many others.
|
Source: http://www.openttd.org
|
||||||
Upstream homepage: http://www.openttd.org
|
|
||||||
|
|
||||||
Copyright © 2004-2009 Ludvig Strigeous and others.
|
Files: *
|
||||||
|
Copyright: © 2004-2012 Ludvig Strigeous and others.
|
||||||
OpenTTD License:
|
License: GPL-2.0
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License version 2.0 as
|
||||||
it under the terms of the GNU General Public License version 2.0 as
|
published by the Free Software Foundation;
|
||||||
published by the Free Software Foundation;
|
.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
||||||
GNU General Public License for more details.
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
You should have received a copy of the GNU General Public License
|
along with this package; if not, write to the Free Software
|
||||||
along with this package; if not, write to the Free Software
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public License
|
||||||
On Debian systems, the complete text of the GNU General Public License
|
version 2 can be found in `/usr/share/common-licenses/GPL-2'.
|
||||||
version 2 can be found in `/usr/share/common-licenses/GPL-2'.
|
|
||||||
|
Files: src/3rdparty/squirrel/*
|
||||||
This package contains an embedded version of the "Squirrel" programming
|
Copyright: © 2003-2009 Alberto Demichelis
|
||||||
language, which is shipped under the following license:
|
License: Zlib
|
||||||
|
|
||||||
Copyright (c) 2003-2009 Alberto Demichelis
|
Files: src/3rdparty/md5/*
|
||||||
|
Copyright: © 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||||
This software is provided 'as-is', without any
|
License: Zlib
|
||||||
express or implied warranty. In no event will the
|
|
||||||
authors be held liable for any damages arising from
|
|
||||||
the use of this software.
|
License: Zlib
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
Permission is granted to anyone to use this software
|
warranty. In no event will the authors be held liable for any damages
|
||||||
for any purpose, including commercial applications,
|
arising from the use of this software.
|
||||||
and to alter it and redistribute it freely, subject
|
.
|
||||||
to the following restrictions:
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
1. The origin of this software must not be
|
freely, subject to the following restrictions:
|
||||||
misrepresented; you must not claim that
|
.
|
||||||
you wrote the original software. If you
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
use this software in a product, an
|
claim that you wrote the original software. If you use this software in
|
||||||
acknowledgment in the product
|
a product, an acknowledgment in the product documentation would be
|
||||||
documentation would be appreciated but is
|
appreciated but is not required.
|
||||||
not required.
|
.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not
|
||||||
2. Altered source versions must be plainly
|
be misrepresented as being the original software.
|
||||||
marked as such, and must not be
|
.
|
||||||
misrepresented as being the original
|
3. This notice may not be removed or altered from any source
|
||||||
software.
|
distribution.
|
||||||
|
|
||||||
3. This notice may not be removed or
|
Files: os/dos/exe2coff/*
|
||||||
altered from any source distribution.
|
Copyright: © 1998 DJ Delorie
|
||||||
|
License: GPL-2.0 with additional restrictions
|
||||||
This package contains an implementation of the md5 hash algorithm, which
|
This document is Copyright (C) DJ Delorie and may be distributed
|
||||||
is shipped under the following license:
|
verbatim, but changing it is not allowed.
|
||||||
|
.
|
||||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
Source code copyright DJ Delorie is distributed under the terms of the
|
||||||
|
GNU General Public Licence, with the following exceptions:
|
||||||
This software is provided 'as-is', without any express or implied
|
.
|
||||||
warranty. In no event will the authors be held liable for any damages
|
* Sources used to build crt0.o, gcrt0.o, libc.a, libdbg.a, and
|
||||||
arising from the use of this software.
|
libemu.a are distributed under the terms of the GNU Library General
|
||||||
|
Public License, rather than the GNU GPL.
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
.
|
||||||
including commercial applications, and to alter it and redistribute it
|
* Any existing copyright or authorship information in any given source
|
||||||
freely, subject to the following restrictions:
|
file must remain intact. If you modify a source file, a notice to that
|
||||||
|
effect must be added to the authorship information in the source file.
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
.
|
||||||
claim that you wrote the original software. If you use this software
|
* Runtime binaries, as provided by DJ in DJGPP, may be distributed
|
||||||
in a product, an acknowledgment in the product documentation would be
|
without sources ONLY if the recipient is given sufficient information
|
||||||
appreciated but is not required.
|
to obtain a copy of djgpp themselves. This primarily applies to
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
go32-v2.exe, emu387.dxe, and stubedit.exe.
|
||||||
misrepresented as being the original software.
|
.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
* Runtime objects and libraries, as provided by DJ in DJGPP, when
|
||||||
|
linked into an application, may be distributed without sources ONLY
|
||||||
|
if the recipient is given sufficient information to obtain a copy of
|
||||||
|
djgpp themselves. This primarily applies to crt0.o and libc.a.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public License
|
||||||
|
version 2 can be found in `/usr/share/common-licenses/GPL-2'.
|
||||||
|
Comment:
|
||||||
|
Given only the exe2coff.c file is distributed in the source distribution (and
|
||||||
|
nothing in Debian binary distribution), it seems only the 2nd condition
|
||||||
|
applies.
|
||||||
|
|
||||||
|
Files: os/dos/cwsdpmi/*
|
||||||
|
Source: http://homer.rice.edu/~sandmann/cwsdpmi/index.html
|
||||||
|
Copyright: © 1995-2000 Charles W Sandmann (sandmann@clio.rice.edu)
|
||||||
|
License: Custom binary-only license
|
||||||
|
This is release 5. The files in this binary distribution may be redistributed
|
||||||
|
under the GPL (with source) or without the source code provided:
|
||||||
|
.
|
||||||
|
* CWSDPMI.EXE or CWSDPR0.EXE are not modified in any way except via CWSPARAM.
|
||||||
|
.
|
||||||
|
* CWSDSTUB.EXE internal contents are not modified in any way except via
|
||||||
|
CWSPARAM or STUBEDIT. It may have a COFF image plus data appended to it.
|
||||||
|
.
|
||||||
|
* Notice to users that they have the right to receive the source code and/or
|
||||||
|
binary updates for CWSDPMI. Distributors should indicate a site for the
|
||||||
|
source in their documentation.
|
||||||
|
Comment:
|
||||||
|
Files are distributed as binary only, so the second option in the license
|
||||||
|
("without source code provided: ...") is applicable.
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
?package(openttd):needs="X11" section="Games/Simulation" title="OpenTTD"\
|
?package(openttd):needs="X11" section="Games/Simulation" title="OpenTTD"\
|
||||||
command="/usr/share/games/openttd/openttd-wrapper" icon="/usr/share/pixmaps/openttd.32.xpm"
|
command="/usr/games/openttd" icon="/usr/share/pixmaps/openttd.32.xpm"
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
The files in this directory are not licensed under the same terms as the
|
||||||
|
rest of OpenTTD. Licensing details can be found in OpenTTD's readme.txt
|
||||||
|
and in this directory or subdirectories as well.
|
@ -0,0 +1,3 @@
|
|||||||
|
The files in this directory are not licensed under the same terms as the
|
||||||
|
rest of OpenTTD. Licensing details can be found in OpenTTD's readme.txt
|
||||||
|
and in this directory or subdirectories as well.
|
@ -0,0 +1,3 @@
|
|||||||
|
The files in this directory are not licensed under the same terms as the
|
||||||
|
rest of OpenTTD. Licensing details can be found in OpenTTD's readme.txt
|
||||||
|
and in this directory or subdirectories as well.
|
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of libESMTP, a library for submission of RFC 2822
|
||||||
|
* formatted electronic mail messages using the SMTP protocol described
|
||||||
|
* in RFC 2821.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* An emulation of the RFC 2553 / Posix getaddrinfo resolver interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !HAVE_GETADDRINFO
|
||||||
|
|
||||||
|
/* Need to turn off Posix features in glibc to build this */
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#undef _XOPEN_SOURCE
|
||||||
|
|
||||||
|
#include "getaddrinfo.h"
|
||||||
|
//#include "compat/inet_pton.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
static struct addrinfo *
|
||||||
|
dup_addrinfo (struct addrinfo *info, void *addr, size_t addrlen) {
|
||||||
|
struct addrinfo *ret;
|
||||||
|
|
||||||
|
ret = malloc (sizeof (struct addrinfo));
|
||||||
|
if (ret == NULL)
|
||||||
|
return NULL;
|
||||||
|
memcpy (ret, info, sizeof (struct addrinfo));
|
||||||
|
ret->ai_addr = malloc (addrlen);
|
||||||
|
if (ret->ai_addr == NULL) {
|
||||||
|
free (ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy (ret->ai_addr, addr, addrlen);
|
||||||
|
ret->ai_addrlen = addrlen;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getaddrinfo (const char *nodename, const char *servname,
|
||||||
|
const struct addrinfo *hints, struct addrinfo **res)
|
||||||
|
{
|
||||||
|
struct hostent *hp;
|
||||||
|
struct servent *servent;
|
||||||
|
const char *socktype;
|
||||||
|
int port;
|
||||||
|
struct addrinfo hint, result;
|
||||||
|
struct addrinfo *ai, *sai, *eai;
|
||||||
|
char **addrs;
|
||||||
|
|
||||||
|
if (servname == NULL && nodename == NULL)
|
||||||
|
return EAI_NONAME;
|
||||||
|
|
||||||
|
memset (&result, 0, sizeof result);
|
||||||
|
|
||||||
|
/* default for hints */
|
||||||
|
if (hints == NULL) {
|
||||||
|
memset (&hint, 0, sizeof hint);
|
||||||
|
hint.ai_family = PF_UNSPEC;
|
||||||
|
hints = &hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servname == NULL)
|
||||||
|
port = 0;
|
||||||
|
else {
|
||||||
|
/* check for tcp or udp sockets only */
|
||||||
|
if (hints->ai_socktype == SOCK_STREAM)
|
||||||
|
socktype = "tcp";
|
||||||
|
else if (hints->ai_socktype == SOCK_DGRAM)
|
||||||
|
socktype = "udp";
|
||||||
|
else
|
||||||
|
return EAI_SERVICE;
|
||||||
|
result.ai_socktype = hints->ai_socktype;
|
||||||
|
|
||||||
|
/* Note: maintain port in host byte order to make debugging easier */
|
||||||
|
if (isdigit (*servname))
|
||||||
|
port = strtol (servname, NULL, 10);
|
||||||
|
else if ((servent = getservbyname (servname, socktype)) != NULL)
|
||||||
|
port = ntohs (servent->s_port);
|
||||||
|
else
|
||||||
|
return EAI_NONAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if nodename == NULL refer to the local host for a client or any
|
||||||
|
for a server */
|
||||||
|
if (nodename == NULL) {
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
|
/* check protocol family is PF_UNSPEC or PF_INET - could try harder
|
||||||
|
for IPv6 but that's more code than I'm prepared to write */
|
||||||
|
if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET)
|
||||||
|
result.ai_family = AF_INET;
|
||||||
|
else
|
||||||
|
return EAI_FAMILY;
|
||||||
|
|
||||||
|
sin.sin_family = result.ai_family;
|
||||||
|
sin.sin_port = htons (port);
|
||||||
|
if (hints->ai_flags & AI_PASSIVE)
|
||||||
|
sin.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||||
|
else
|
||||||
|
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||||
|
/* Duplicate result and addr and return */
|
||||||
|
*res = dup_addrinfo (&result, &sin, sizeof sin);
|
||||||
|
return (*res == NULL) ? EAI_MEMORY : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If AI_NUMERIC is specified, use inet_pton to translate numbers and
|
||||||
|
dots notation. */
|
||||||
|
if (hints->ai_flags & AI_NUMERICHOST) {
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
|
/* check protocol family is PF_UNSPEC or PF_INET */
|
||||||
|
if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET)
|
||||||
|
result.ai_family = AF_INET;
|
||||||
|
else
|
||||||
|
return EAI_FAMILY;
|
||||||
|
|
||||||
|
sin.sin_family = result.ai_family;
|
||||||
|
sin.sin_port = htons (port);
|
||||||
|
if (inet_pton(result.ai_family, nodename, &sin.sin_addr)==0)
|
||||||
|
return EAI_NONAME;
|
||||||
|
sin.sin_addr.s_addr = inet_addr (nodename);
|
||||||
|
/* Duplicate result and addr and return */
|
||||||
|
*res = dup_addrinfo (&result, &sin, sizeof sin);
|
||||||
|
return (*res == NULL) ? EAI_MEMORY : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_H_ERRNO
|
||||||
|
h_errno = 0;
|
||||||
|
#endif
|
||||||
|
errno = 0;
|
||||||
|
hp = gethostbyname(nodename);
|
||||||
|
if (hp == NULL) {
|
||||||
|
#ifdef EAI_SYSTEM
|
||||||
|
if (errno != 0) {
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
switch (h_errno) {
|
||||||
|
case HOST_NOT_FOUND:
|
||||||
|
return EAI_NODATA;
|
||||||
|
case NO_DATA:
|
||||||
|
return EAI_NODATA;
|
||||||
|
#if defined(NO_ADDRESS) && NO_ADDRESS != NO_DATA
|
||||||
|
case NO_ADDRESS:
|
||||||
|
return EAI_NODATA;
|
||||||
|
#endif
|
||||||
|
case NO_RECOVERY:
|
||||||
|
return EAI_FAIL;
|
||||||
|
case TRY_AGAIN:
|
||||||
|
return EAI_AGAIN;
|
||||||
|
default:
|
||||||
|
return EAI_FAIL;
|
||||||
|
}
|
||||||
|
return EAI_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the address family is acceptable.
|
||||||
|
*/
|
||||||
|
switch (hp->h_addrtype) {
|
||||||
|
case AF_INET:
|
||||||
|
if (!(hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET))
|
||||||
|
return EAI_FAMILY;
|
||||||
|
break;
|
||||||
|
#ifndef __OS2__
|
||||||
|
case AF_INET6:
|
||||||
|
if (!(hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET6))
|
||||||
|
return EAI_FAMILY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return EAI_FAMILY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For each element pointed to by hp, create an element in the
|
||||||
|
result linked list. */
|
||||||
|
sai = eai = NULL;
|
||||||
|
for (addrs = hp->h_addr_list; *addrs != NULL; addrs++) {
|
||||||
|
struct sockaddr sa;
|
||||||
|
size_t addrlen;
|
||||||
|
|
||||||
|
if (hp->h_length < 1)
|
||||||
|
continue;
|
||||||
|
sa.sa_family = hp->h_addrtype;
|
||||||
|
switch (hp->h_addrtype) {
|
||||||
|
case AF_INET:
|
||||||
|
((struct sockaddr_in *) &sa)->sin_port = htons (port);
|
||||||
|
memcpy (&((struct sockaddr_in *) &sa)->sin_addr,
|
||||||
|
*addrs, hp->h_length);
|
||||||
|
addrlen = sizeof (struct sockaddr_in);
|
||||||
|
break;
|
||||||
|
#ifndef __OS2__
|
||||||
|
case AF_INET6:
|
||||||
|
#if SIN6_LEN
|
||||||
|
((struct sockaddr_in6 *) &sa)->sin6_len = hp->h_length;
|
||||||
|
#endif
|
||||||
|
((struct sockaddr_in6 *) &sa)->sin6_port = htons (port);
|
||||||
|
memcpy (&((struct sockaddr_in6 *) &sa)->sin6_addr,
|
||||||
|
*addrs, hp->h_length);
|
||||||
|
addrlen = sizeof (struct sockaddr_in6);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.ai_family = hp->h_addrtype;
|
||||||
|
ai = dup_addrinfo (&result, &sa, addrlen);
|
||||||
|
if (ai == NULL) {
|
||||||
|
freeaddrinfo (sai);
|
||||||
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
if (sai == NULL)
|
||||||
|
sai = ai;
|
||||||
|
else
|
||||||
|
eai->ai_next = ai;
|
||||||
|
eai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sai == NULL) {
|
||||||
|
return EAI_NODATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hints->ai_flags & AI_CANONNAME) {
|
||||||
|
sai->ai_canonname = malloc (strlen (hp->h_name) + 1);
|
||||||
|
if (sai->ai_canonname == NULL) {
|
||||||
|
freeaddrinfo (sai);
|
||||||
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
strcpy (sai->ai_canonname, hp->h_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
*res = sai;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
freeaddrinfo (struct addrinfo *ai)
|
||||||
|
{
|
||||||
|
struct addrinfo *next;
|
||||||
|
|
||||||
|
while (ai != NULL) {
|
||||||
|
next = ai->ai_next;
|
||||||
|
if (ai->ai_canonname != NULL)
|
||||||
|
free (ai->ai_canonname);
|
||||||
|
if (ai->ai_addr != NULL)
|
||||||
|
free (ai->ai_addr);
|
||||||
|
free (ai);
|
||||||
|
ai = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gai_strerror (int ecode)
|
||||||
|
{
|
||||||
|
static const char *eai_descr[] = {
|
||||||
|
"no error",
|
||||||
|
"address family for nodename not supported", /* EAI_ADDRFAMILY */
|
||||||
|
"temporary failure in name resolution", /* EAI_AGAIN */
|
||||||
|
"invalid value for ai_flags", /* EAI_BADFLAGS */
|
||||||
|
"non-recoverable failure in name resolution", /* EAI_FAIL */
|
||||||
|
"ai_family not supported", /* EAI_FAMILY */
|
||||||
|
"memory allocation failure", /* EAI_MEMORY */
|
||||||
|
"no address associated with nodename", /* EAI_NODATA */
|
||||||
|
"nodename nor servname provided, or not known", /* EAI_NONAME */
|
||||||
|
"servname not supported for ai_socktype", /* EAI_SERVICE */
|
||||||
|
"ai_socktype not supported", /* EAI_SOCKTYPE */
|
||||||
|
"system error returned in errno", /* EAI_SYSTEM */
|
||||||
|
"argument buffer overflow", /* EAI_OVERFLOW */
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ecode < 0 || ecode > (int) (sizeof eai_descr/ sizeof eai_descr[0]))
|
||||||
|
return "unknown error";
|
||||||
|
return eai_descr[ecode];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GETADDRINFO */
|
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef _getaddrinfo_h
|
||||||
|
#define _getaddrinfo_h
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shamelessly duplicated from the fetchmail public sources
|
||||||
|
* for use by the Squid Project under GNU Public License.
|
||||||
|
*
|
||||||
|
* Update/Maintenance History:
|
||||||
|
*
|
||||||
|
* 15-Aug-2007 : Copied from fetchmail 6.3.8
|
||||||
|
* - added protection around libray headers
|
||||||
|
*
|
||||||
|
* 16-Aug-2007 : Altered configure checks
|
||||||
|
* Un-hacked slightly to use system gethostbyname()
|
||||||
|
*
|
||||||
|
* Original License and code follows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of libESMTP, a library for submission of RFC 2822
|
||||||
|
* formatted electronic mail messages using the SMTP protocol described
|
||||||
|
* in RFC 2821.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Structure and prototypes taken from RFC 2553 */
|
||||||
|
|
||||||
|
/* SG 23/09/2007:
|
||||||
|
On Windows the following definitions are already available, may be that
|
||||||
|
this could be needed on some other platform */
|
||||||
|
typedef int socklen_t;
|
||||||
|
|
||||||
|
struct addrinfo {
|
||||||
|
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
|
||||||
|
int ai_family; /* PF_xxx */
|
||||||
|
int ai_socktype; /* SOCK_xxx */
|
||||||
|
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||||
|
socklen_t ai_addrlen; /* length of ai_addr */
|
||||||
|
char *ai_canonname; /* canonical name for nodename */
|
||||||
|
struct sockaddr *ai_addr; /* binary address */
|
||||||
|
struct addrinfo *ai_next; /* next structure in linked list */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supposed to be defined in <netdb.h> */
|
||||||
|
#define AI_ADDRCONFIG 0
|
||||||
|
#define AI_PASSIVE 1 /* Socket address is intended for `bind'. */
|
||||||
|
#define AI_CANONNAME 2 /* Request for canonical name. */
|
||||||
|
#define AI_NUMERICHOST 4 /* Don't use name resolution. */
|
||||||
|
|
||||||
|
/* Supposed to be defined in <netdb.h> */
|
||||||
|
#define EAI_ADDRFAMILY 1 /* address family for nodename not supported */
|
||||||
|
#define EAI_AGAIN 2 /* temporary failure in name resolution */
|
||||||
|
#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
|
||||||
|
#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
|
||||||
|
#define EAI_FAMILY 5 /* ai_family not supported */
|
||||||
|
#define EAI_MEMORY 6 /* memory allocation failure */
|
||||||
|
#define EAI_NODATA 7 /* no address associated with nodename */
|
||||||
|
#define EAI_NONAME 8 /* nodename nor servname provided, or not known */
|
||||||
|
#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
|
||||||
|
#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
|
||||||
|
|
||||||
|
#ifndef EAI_SYSTEM
|
||||||
|
/* Not defined on mingw32. */
|
||||||
|
#define EAI_SYSTEM 11 /* System error returned in `errno'. */
|
||||||
|
#endif
|
||||||
|
#ifndef EAI_OVERFLOW
|
||||||
|
/* Not defined on mingw32. */
|
||||||
|
#define EAI_OVERFLOW 12 /* Argument buffer overflow. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* RFC 2553 / Posix resolver */
|
||||||
|
int getaddrinfo (const char *nodename, const char *servname,
|
||||||
|
const struct addrinfo *hints, struct addrinfo **res);
|
||||||
|
/* Free addrinfo structure and associated storage */
|
||||||
|
void freeaddrinfo (struct addrinfo *ai);
|
||||||
|
|
||||||
|
/* Convert error return from getaddrinfo() to string */
|
||||||
|
const char *gai_strerror (int code);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _getaddrinfo_h */
|
@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Issues to be discussed:
|
||||||
|
* - RFC2553 says that we should raise error on short buffer. X/Open says
|
||||||
|
* we need to truncate the result. We obey RFC2553 (and X/Open should be
|
||||||
|
* modified). ipngwg rough consensus seems to follow RFC2553. RFC3493 says
|
||||||
|
* nothing about it, but defines a new error code EAI_OVERFLOW which seems
|
||||||
|
* to be intended the code for this case.
|
||||||
|
* - What is "local" in NI_NOFQDN? (see comments in the code)
|
||||||
|
* - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
|
||||||
|
* - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
|
||||||
|
* sin6_scope_id is filled - standardization status?
|
||||||
|
* - what should we do if we should do getservbyport("sctp")?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Considerations about thread-safeness
|
||||||
|
* The code in this file is thread-safe, and so the thread-safeness of
|
||||||
|
* getnameinfo() depends on the property of backend functions.
|
||||||
|
* - getservbyport() is not thread safe for most systems we are targeting.
|
||||||
|
* - getipnodebyaddr() is thread safe. However, many resolver libraries
|
||||||
|
* used in the function are not thread safe.
|
||||||
|
* - gethostbyaddr() is usually not thread safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !HAVE_GETNAMEINFO
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "getaddrinfo.h"
|
||||||
|
#include "getnameinfo.h"
|
||||||
|
|
||||||
|
static const struct afd {
|
||||||
|
int a_af;
|
||||||
|
int a_addrlen;
|
||||||
|
int a_socklen;
|
||||||
|
int a_off;
|
||||||
|
int a_portoff;
|
||||||
|
} afdl [] = {
|
||||||
|
#if INET6
|
||||||
|
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
||||||
|
offsetof(struct sockaddr_in6, sin6_addr),
|
||||||
|
offsetof(struct sockaddr_in6, sin6_port)},
|
||||||
|
#endif
|
||||||
|
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
||||||
|
offsetof(struct sockaddr_in, sin_addr),
|
||||||
|
offsetof(struct sockaddr_in, sin_port)},
|
||||||
|
{0, 0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
#if INET6
|
||||||
|
static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
|
||||||
|
size_t, int));
|
||||||
|
static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
|
||||||
|
const struct sockaddr *sa;
|
||||||
|
socklen_t salen;
|
||||||
|
char *host;
|
||||||
|
size_t hostlen;
|
||||||
|
char *serv;
|
||||||
|
size_t servlen;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
const struct afd *afd;
|
||||||
|
struct servent *sp;
|
||||||
|
struct hostent *hp;
|
||||||
|
unsigned short port;
|
||||||
|
int family, i;
|
||||||
|
const char *addr;
|
||||||
|
uint32_t v4a;
|
||||||
|
char numserv[512];
|
||||||
|
|
||||||
|
if (sa == NULL)
|
||||||
|
return EAI_FAIL;
|
||||||
|
|
||||||
|
#if HAVE_SA_LEN /*XXX*/
|
||||||
|
if (sa->sa_len != salen)
|
||||||
|
return EAI_FAIL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
family = sa->sa_family;
|
||||||
|
for (i = 0; afdl[i].a_af; i++)
|
||||||
|
if (afdl[i].a_af == family) {
|
||||||
|
afd = &afdl[i];
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
return EAI_FAMILY;
|
||||||
|
|
||||||
|
found:
|
||||||
|
if (salen != afd->a_socklen)
|
||||||
|
return EAI_FAIL;
|
||||||
|
|
||||||
|
/* network byte order */
|
||||||
|
memcpy(&port, (const char *)sa + afd->a_portoff, sizeof(port));
|
||||||
|
addr = (const char *)sa + afd->a_off;
|
||||||
|
|
||||||
|
if (serv == NULL || servlen == 0) {
|
||||||
|
/*
|
||||||
|
* do nothing in this case.
|
||||||
|
* in case you are wondering if "&&" is more correct than
|
||||||
|
* "||" here: RFC3493 says that serv == NULL OR servlen == 0
|
||||||
|
* means that the caller does not want the result.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
if (flags & NI_NUMERICSERV)
|
||||||
|
sp = NULL;
|
||||||
|
else {
|
||||||
|
sp = getservbyport(port,
|
||||||
|
(flags & NI_DGRAM) ? "udp" : "tcp");
|
||||||
|
}
|
||||||
|
if (sp) {
|
||||||
|
if (strlen(sp->s_name) + 1 > servlen)
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
strncpy(serv, sp->s_name, servlen);
|
||||||
|
} else {
|
||||||
|
snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
|
||||||
|
if (strlen(numserv) + 1 > servlen)
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
strncpy(serv, numserv, servlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sa->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
v4a = (uint32_t)
|
||||||
|
ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
|
||||||
|
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
|
||||||
|
flags |= NI_NUMERICHOST;
|
||||||
|
v4a >>= IN_CLASSA_NSHIFT;
|
||||||
|
if (v4a == 0)
|
||||||
|
flags |= NI_NUMERICHOST;
|
||||||
|
break;
|
||||||
|
#if INET6
|
||||||
|
case AF_INET6: {
|
||||||
|
const struct sockaddr_in6 *sin6;
|
||||||
|
sin6 = (const struct sockaddr_in6 *)sa;
|
||||||
|
switch (sin6->sin6_addr.s6_addr[0]) {
|
||||||
|
case 0x00:
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||||
|
;
|
||||||
|
else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
flags |= NI_NUMERICHOST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
|
||||||
|
flags |= NI_NUMERICHOST;
|
||||||
|
else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
|
||||||
|
flags |= NI_NUMERICHOST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (host == NULL || hostlen == 0) {
|
||||||
|
/*
|
||||||
|
* do nothing in this case.
|
||||||
|
* in case you are wondering if "&&" is more correct than
|
||||||
|
* "||" here: RFC3493 says that host == NULL or hostlen == 0
|
||||||
|
* means that the caller does not want the result.
|
||||||
|
*/
|
||||||
|
} else if (flags & NI_NUMERICHOST) {
|
||||||
|
/* NUMERICHOST and NAMEREQD conflicts with each other */
|
||||||
|
if (flags & NI_NAMEREQD)
|
||||||
|
return EAI_NONAME;
|
||||||
|
|
||||||
|
goto numeric;
|
||||||
|
} else {
|
||||||
|
#if USE_GETIPNODEBY
|
||||||
|
int h_error = 0;
|
||||||
|
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
|
||||||
|
#else
|
||||||
|
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
|
||||||
|
#if 0 // getnameinfo.c:161:9: error: variable 'h_error' set but not used
|
||||||
|
#if HAVE_H_ERRNO
|
||||||
|
h_error = h_errno;
|
||||||
|
#else
|
||||||
|
h_error = EINVAL;
|
||||||
|
#endif
|
||||||
|
#endif /* 0 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hp) {
|
||||||
|
#if 0
|
||||||
|
if (flags & NI_NOFQDN) {
|
||||||
|
/*
|
||||||
|
* According to RFC3493 section 6.2, NI_NOFQDN
|
||||||
|
* means "node name portion of the FQDN shall
|
||||||
|
* be returned for local hosts." The following
|
||||||
|
* code tries to implement it by returning the
|
||||||
|
* first label (the part before the first
|
||||||
|
* period) of the FQDN. However, it is not
|
||||||
|
* clear if this always makes sense, since the
|
||||||
|
* given address may be outside of "local
|
||||||
|
* hosts." Due to the unclear description, we
|
||||||
|
* disable the code in this implementation.
|
||||||
|
*/
|
||||||
|
char *p;
|
||||||
|
p = strchr(hp->h_name, '.');
|
||||||
|
if (p)
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (strlen(hp->h_name) + 1 > hostlen) {
|
||||||
|
#if USE_GETIPNODEBY
|
||||||
|
freehostent(hp);
|
||||||
|
#endif
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
}
|
||||||
|
strncpy(host, hp->h_name, hostlen);
|
||||||
|
#if USE_GETIPNODEBY
|
||||||
|
freehostent(hp);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (flags & NI_NAMEREQD)
|
||||||
|
return EAI_NONAME;
|
||||||
|
|
||||||
|
numeric:
|
||||||
|
switch (afd->a_af) {
|
||||||
|
#if INET6
|
||||||
|
case AF_INET6: {
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((error = ip6_parsenumeric(sa, addr, host,
|
||||||
|
hostlen,
|
||||||
|
flags)) != 0)
|
||||||
|
return(error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
if (inet_ntop(afd->a_af, addr, host,
|
||||||
|
hostlen) == NULL)
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INET6
|
||||||
|
static int
|
||||||
|
ip6_parsenumeric(sa, addr, host, hostlen, flags)
|
||||||
|
const struct sockaddr *sa;
|
||||||
|
const char *addr;
|
||||||
|
char *host;
|
||||||
|
size_t hostlen;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
int numaddrlen;
|
||||||
|
char numaddr[512];
|
||||||
|
|
||||||
|
if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
numaddrlen = strlen(numaddr);
|
||||||
|
if (numaddrlen + 1 > hostlen) /* don't forget terminator */
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
strncpy(host, numaddr, hostlen);
|
||||||
|
|
||||||
|
if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
|
||||||
|
char zonebuf[SQUIDHOSTNAMELEN];
|
||||||
|
int zonelen;
|
||||||
|
|
||||||
|
zonelen = ip6_sa2str(
|
||||||
|
(const struct sockaddr_in6 *)(const void *)sa,
|
||||||
|
zonebuf, sizeof(zonebuf), flags);
|
||||||
|
if (zonelen < 0)
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
if (zonelen + 1 + numaddrlen + 1 > hostlen)
|
||||||
|
return EAI_OVERFLOW;
|
||||||
|
|
||||||
|
/* construct <numeric-addr><delim><zoneid> */
|
||||||
|
memcpy(host + numaddrlen + 1, zonebuf,
|
||||||
|
(size_t)zonelen);
|
||||||
|
host[numaddrlen] = SCOPE_DELIMITER;
|
||||||
|
host[numaddrlen + 1 + zonelen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
static int
|
||||||
|
ip6_sa2str(sa6, buf, bufsiz, flags)
|
||||||
|
const struct sockaddr_in6 *sa6;
|
||||||
|
char *buf;
|
||||||
|
size_t bufsiz;
|
||||||
|
int flags;
|
||||||
|
{
|
||||||
|
unsigned int ifindex;
|
||||||
|
const struct in6_addr *a6;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ifindex = (unsigned int)sa6->sin6_scope_id;
|
||||||
|
a6 = &sa6->sin6_addr;
|
||||||
|
|
||||||
|
#if NI_NUMERICSCOPE
|
||||||
|
if ((flags & NI_NUMERICSCOPE) != 0) {
|
||||||
|
n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
|
||||||
|
if (n < 0 || n >= bufsiz)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if_indextoname() does not take buffer size. not a good api... */
|
||||||
|
if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
|
||||||
|
IN6_IS_ADDR_MC_NODELOCAL(a6)) && bufsiz >= IF_NAMESIZE) {
|
||||||
|
char *p = if_indextoname(ifindex, buf);
|
||||||
|
if (p)
|
||||||
|
return (strlen(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* last resort */
|
||||||
|
n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
|
||||||
|
if (n < 0 || n >= bufsiz)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
#endif /* INET6 */
|
||||||
|
#endif
|
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _getnameinfo_h
|
||||||
|
#define _getnameinfo_h
|
||||||
|
/*
|
||||||
|
* Reconstructed from KAME getnameinfo.c (in lib/)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* getnameinfo flags */
|
||||||
|
#define NI_NOFQDN 0x0001
|
||||||
|
#define NI_NUMERICHOST 0x0002 /* return numeric form of address */
|
||||||
|
#define NI_NAMEREQD 0x0004 /* request DNS name */
|
||||||
|
#define NI_NUMERICSERV 0x0008
|
||||||
|
#define NI_DGRAM 0x0010
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* RFC 2553 / Posix resolver */
|
||||||
|
int getnameinfo(const struct sockaddr *sa,
|
||||||
|
socklen_t salen,
|
||||||
|
char *host,
|
||||||
|
size_t hostlen,
|
||||||
|
char *serv,
|
||||||
|
size_t servlen,
|
||||||
|
int flags );
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _getnameinfo_h */
|
@ -1,41 +0,0 @@
|
|||||||
Squirrel 2.2.4 stable
|
|
||||||
--------------------------------------------------------
|
|
||||||
What is in this distribution?
|
|
||||||
|
|
||||||
squirrel
|
|
||||||
static library implementing the compiler and interpreter of the language
|
|
||||||
|
|
||||||
sqstdlib
|
|
||||||
the standard utility libraries
|
|
||||||
|
|
||||||
sq
|
|
||||||
stand alone interpreter
|
|
||||||
|
|
||||||
doc
|
|
||||||
The manual
|
|
||||||
|
|
||||||
etc
|
|
||||||
a minimalistic embedding sample
|
|
||||||
|
|
||||||
samples
|
|
||||||
samples programs
|
|
||||||
|
|
||||||
|
|
||||||
HOW TO COMPILE
|
|
||||||
---------------------------------------------------------
|
|
||||||
GCC USERS
|
|
||||||
.........................................................
|
|
||||||
There is a very simple makefile that compiles all libraries and exes
|
|
||||||
from the root of the project run 'make'
|
|
||||||
|
|
||||||
for 32 bits systems
|
|
||||||
|
|
||||||
$ make
|
|
||||||
|
|
||||||
for 64 bits systems
|
|
||||||
|
|
||||||
$ make sq64
|
|
||||||
|
|
||||||
VISUAL C++ USERS
|
|
||||||
.........................................................
|
|
||||||
Open squirrel.dsw from the root project directory and build(dho!)
|
|
@ -1,357 +0,0 @@
|
|||||||
***version 2.2.5 stable***
|
|
||||||
-sq_getsize() now returns userdatasize for classes and instances
|
|
||||||
-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)
|
|
||||||
-now array.sort() is implemented with heapsort
|
|
||||||
-added SQUIRREL_VERSION_NUMBER preprocessor definition
|
|
||||||
-now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6)
|
|
||||||
-fixed some compiler warning
|
|
||||||
-fixed a minor compiler bug
|
|
||||||
-fixed some bugs when SQUSEDOUBLE is used in 32bits systems
|
|
||||||
-fixed bug in GC
|
|
||||||
|
|
||||||
***2009-11-15 ***
|
|
||||||
***version 2.2.4 stable***
|
|
||||||
-fixed bug in functions with default parameters
|
|
||||||
|
|
||||||
***2009-06-30 ***
|
|
||||||
***version 2.2.3 stable***
|
|
||||||
-added sq_getfunctioninfo
|
|
||||||
-added compile time flag SQUSEDOUBLE to use double precision floats
|
|
||||||
-added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
|
|
||||||
-sq_wakeupvm can now resume the vm with an exception
|
|
||||||
-added sqstd_format
|
|
||||||
-generators can now be instantiated by calling sq_call() or closure.call()
|
|
||||||
-fixed a bug in sqstd_printcallstack(thx takayuki_h)
|
|
||||||
-fixed modulo by zero(thx jup)
|
|
||||||
-fixed negative enums and constants
|
|
||||||
-fixed generator crash bug if invoked as tail call (thx Mr.Accident)
|
|
||||||
-fixed some minor bug
|
|
||||||
|
|
||||||
***2008-09-24 ***
|
|
||||||
***version 2.2.2 stable***
|
|
||||||
-fixed some behaviour inconsistencies in thread.call() and thread.wakeup() (thx Mr.Accident)
|
|
||||||
-fixed coroutine error propagation
|
|
||||||
-fixed lingering return value from native function (thx Tom Leonard)
|
|
||||||
-fixed a bug if array.sort() is given a bad sort function (thx Tom Leonard)
|
|
||||||
-fixed some minor api bug
|
|
||||||
-added sq_arrayremove() and sq_arrayinsert()
|
|
||||||
|
|
||||||
***2008-05-16 ***
|
|
||||||
***version 2.2.1 stable***
|
|
||||||
-fixed a tailcall bug
|
|
||||||
|
|
||||||
***2008-02-17 ***
|
|
||||||
***version 2.2 stable ***
|
|
||||||
-added _newslot metamethod in classes
|
|
||||||
-added enums added constants
|
|
||||||
-added sq_pushconsttable, sq_setconsttable
|
|
||||||
-added default param
|
|
||||||
-added octal literals(thx Dinosaur)
|
|
||||||
-fixed debug hook, 'calls' and 'returns' are properly notified in the same number.
|
|
||||||
-fixed a coroutine bug
|
|
||||||
|
|
||||||
***2007-07-29 ***
|
|
||||||
***version 2.1.2 stable***
|
|
||||||
-new behaviour for generators iteration using foreach
|
|
||||||
now when a generator is iterated by foreach the value returned by a 'return val' statement
|
|
||||||
will terminate the iteration but will not be returned as foreach iteration
|
|
||||||
-added sq_setclassudsize()
|
|
||||||
-added sq_clear()
|
|
||||||
-added table.clear(), array.clear()
|
|
||||||
-fixed sq_cmp() (thx jyuill)
|
|
||||||
-fixed minor bugs
|
|
||||||
|
|
||||||
***2006-08-21 ***
|
|
||||||
***version 2.1.1 stable***
|
|
||||||
-vm refactoring
|
|
||||||
-optimized internal function memory layout
|
|
||||||
-new global symbol _version_ (is the version string)
|
|
||||||
-code size optimization for float literals(on 32bits float builts)
|
|
||||||
-now the raw ref API(sq_addref etc...) is fully reentrant.
|
|
||||||
-fixed a bug in sq_getdelegate() now pushes null if the object doesn't have a delegate(thx MatzeB)
|
|
||||||
-improved C reference performances in NO_GARBAGE_COLLECTOR builds
|
|
||||||
-sq_getlocal() now enumerates also outer values.
|
|
||||||
-fixed regexp library for GCC users.
|
|
||||||
|
|
||||||
***2006-03-19 ***
|
|
||||||
***version 2.1 stable***
|
|
||||||
-added static class fields, new keyword static
|
|
||||||
-added 64bits architecture support
|
|
||||||
-added global slot _intsize_ int the base lib to recognize 32bits and 64bits builds
|
|
||||||
-added functions with fixed environment, closure.bindenv() built-in function
|
|
||||||
-all types except userdata and null implement the tostring() method
|
|
||||||
-string concatenation now invokes metamethod _tostring
|
|
||||||
-new metamethods for class objects _newmember and _inherited
|
|
||||||
-sq_call() sq_resume() sq_wakeupvm() have a new signature
|
|
||||||
-new C referencing implementation(scales more with the amount of references)
|
|
||||||
-refactored hash table
|
|
||||||
-new api functions sq_newslot(),sq_tobool(),sq_getbase(), sq_instanceof(), sq_bindenv()
|
|
||||||
-the api func sq_createslot was deprecated but still supported in form of C macro on top of sq_newslot
|
|
||||||
-sq_setreleasehook() now also works for classes
|
|
||||||
-stream.readstr() and stream.writestr() have been deprecated(this affects file and blob)
|
|
||||||
-fixed squirrel.h undeclared api calls
|
|
||||||
-fixed few minor bugs
|
|
||||||
-SQChar is now defined as wchar_t
|
|
||||||
-removed warning when building with -Wall -pedantic for GCC users
|
|
||||||
-added new std io function writeclosuretofile()
|
|
||||||
-added new std string functions strip(),rstrip(),lstrip() and split()
|
|
||||||
-regular expressions operators (+,*) now have more POSIX greedyness behaviour
|
|
||||||
-class constructors are now invoked as normal functions
|
|
||||||
|
|
||||||
***2005-10-02 ***
|
|
||||||
***version 2.0.5 stable***
|
|
||||||
-fixed some 64bits incompatibilities (thx sarge)
|
|
||||||
-fixed minor bug in the stdlib format() function (thx Rick)
|
|
||||||
-fixed a bug in dofile() that was preventing to compile empty files
|
|
||||||
-added new API sq_poptop() & sq_getfreevariable()
|
|
||||||
-some performance improvements
|
|
||||||
|
|
||||||
***2005-08-14 ***
|
|
||||||
***version 2.0.4 stable***
|
|
||||||
-weak references and related API calls
|
|
||||||
-added sq_objtobool()
|
|
||||||
-class instances memory policies improved(1 mem allocation for the whole instance)
|
|
||||||
-typetags are now declared as SQUserPointer instead of unsigned int
|
|
||||||
-first pass for 64bits compatibility
|
|
||||||
-fixed minor bug in the stdio stream
|
|
||||||
-fixed a bug in format()
|
|
||||||
-fixed bug in string.tointeger() and string.tofloat()
|
|
||||||
|
|
||||||
***2005-06-24 ***
|
|
||||||
***version 2.0.3 stable***
|
|
||||||
-dofile() and loadfile() in the iolib now can decode ASCII, UTF8 files UCS2 big-endian and little-endian
|
|
||||||
-sq_setparamscheck() : now typemesk can check for null
|
|
||||||
-added string escape sequence \xhhhh
|
|
||||||
-fixed some C++ standard incompatibilities
|
|
||||||
|
|
||||||
***2005-05-15 ***
|
|
||||||
***version 2.0.2 stable***
|
|
||||||
-performances improvements (expecially for GCC users)
|
|
||||||
-removed all dependencies from C++ exception handling
|
|
||||||
-various bugfixes
|
|
||||||
|
|
||||||
***2005-04-12 ***
|
|
||||||
***version 2.0.1 stable***
|
|
||||||
-various bugfixes
|
|
||||||
-sq_setparamscheck() now allows spaces in the typemask
|
|
||||||
|
|
||||||
***2005-04-03 ***
|
|
||||||
***version 2.0 stable***
|
|
||||||
-added API sq_gettypetag()
|
|
||||||
-added built-in function to the bool type(tointeger, tostring etc...)
|
|
||||||
|
|
||||||
***2005-02-27 ***
|
|
||||||
***version 2.0 release candidate 1(RC 1)***
|
|
||||||
-added API sq_reseterror()
|
|
||||||
-modified sq_release()
|
|
||||||
-now class instances can be cloned
|
|
||||||
-various bufixes
|
|
||||||
|
|
||||||
***2005-01-26 ***
|
|
||||||
***version 2.0 beta 1***
|
|
||||||
-added bool type
|
|
||||||
-class properties can be redefined in a derived class
|
|
||||||
-added ops *= /= and %=
|
|
||||||
-new syntax for class attributes declaration </ and /> instead of ( and )
|
|
||||||
-increased the max number of literals per function from 65535 to 16777215
|
|
||||||
-now free variables have proper lexical scoping
|
|
||||||
-added API sq_createinstance(), sq_pushbool(), sq_getbool()
|
|
||||||
-added built-in function type()
|
|
||||||
-added built-in function obj.rawin(key) in table,class and instance
|
|
||||||
-sq_rawget() and sq_rawset() now work also on classes and instances
|
|
||||||
-the VM no longer uses C++ exception handling (more suitable for embedded devices)
|
|
||||||
-various bufixes
|
|
||||||
|
|
||||||
***2004-12-21 ***
|
|
||||||
***version 2.0 alpha 2***
|
|
||||||
-globals scoping changed, now if :: is omitted the VM automatically falls back on the root table
|
|
||||||
-various bufixes
|
|
||||||
-added class level attributes
|
|
||||||
|
|
||||||
***2004-12-12 ***
|
|
||||||
***version 2.0 alpha 1***
|
|
||||||
-codebase branch from version 1.x
|
|
||||||
-added classes
|
|
||||||
-added functions with variable number of parameters(vargc & vargv and the ...)
|
|
||||||
-0 and 0.0 are now considered 'false' by all conditional statements(if,while,for,?,do-while)
|
|
||||||
-added new api functions sq_newclass() sq_setinstanceup() sq_getinstanceup() sq_getattributes() sq_setattributes()
|
|
||||||
-modified api sq_settypetag()
|
|
||||||
|
|
||||||
***2004-11-01 ***
|
|
||||||
***version 1.0 stable***
|
|
||||||
-fixed some minor bug
|
|
||||||
-improoved operator 'delete' performances
|
|
||||||
-added scientific notation for float numbers( eg. 2.e16 or 2.e-2)
|
|
||||||
|
|
||||||
***2004-08-30 ***
|
|
||||||
***version 1.0 release candidate 2(RC 2)***
|
|
||||||
-fixed bug in the vm(thx Pierre Renaux)
|
|
||||||
-fixed bug in the optimizer(thx Pierre Renaux)
|
|
||||||
-fixed some bug in the documentation(thx JD)
|
|
||||||
-added new api functions for raw object handling
|
|
||||||
-removed nested multiline comments
|
|
||||||
-reduced memory footprint in C references
|
|
||||||
|
|
||||||
***2004-08-23 ***
|
|
||||||
***version 1.0 release candidate 1(RC 1)***
|
|
||||||
-fixed division by zero
|
|
||||||
-the 'in' operator and obj.rawget() do not query the default delegate anymore
|
|
||||||
-added function sq_getprintfunc()
|
|
||||||
-added new standard library 'auxlib'(implements default error handlers)
|
|
||||||
|
|
||||||
***2004-07-12 ***
|
|
||||||
***version 1.0 beta 4***
|
|
||||||
-fixed a bug in the integer.tochar() built-in method
|
|
||||||
-fixed unary minus operator
|
|
||||||
-fixed bug in dofile()
|
|
||||||
-fixed inconsistency between != and == operators(on float/integer comparison)
|
|
||||||
-added javascript style unsigned right shift operator '>>>'
|
|
||||||
-added array(size) constructor built-in function
|
|
||||||
-array.resize(size,[fill]) built-in function accepts an optional 'fill' value
|
|
||||||
-improved debug API, added sq_getclosureinfo() and sq_setnativeclosurename()
|
|
||||||
|
|
||||||
***2004-05-23 ***
|
|
||||||
***version 1.0 beta 3***
|
|
||||||
-minor vm bug fixes
|
|
||||||
-string allocation is now faster
|
|
||||||
-tables and array memory usage is now less conservative(they shrink)
|
|
||||||
-added regular expression routines in the standard library
|
|
||||||
-The 'c' expression now accepts only 1 character(thx irbrian)
|
|
||||||
-multiline strings <[ ]> have been substituted with C# style verbatim strings (eg. @"string")
|
|
||||||
-added new keyword 'parent' for accessing the delegate of tables and unserdata
|
|
||||||
-The metamethod '_clone' has been renamed '_cloned'
|
|
||||||
-the _delslot metamethod's behaviour and prototype have been changed
|
|
||||||
-new default function in the integer and float object 'tochar()'
|
|
||||||
-the built-in function chcode2string has been removed
|
|
||||||
-the default method [table].getdelegate() has been removed
|
|
||||||
-new api sq_rawdeleteslot()
|
|
||||||
-new table built-in method rawdelete(key)
|
|
||||||
-the dynamic mudule loading has been removed from the standard distribution
|
|
||||||
-some optimizations in the VM
|
|
||||||
|
|
||||||
***2004-04-21 ***
|
|
||||||
***version 1.0 beta 2***
|
|
||||||
-minor compiler/parser bug fixes
|
|
||||||
-sq_newclosure has a different prototype, the "paramscheck" of paramter has been moved to the new function sq_setparamscheck()
|
|
||||||
-sq_setparamscheck allows to add automatic parameters type checking in native closures
|
|
||||||
-sq_compile() lost the lineinfo parameter
|
|
||||||
-new api sq_enabledebuginfo() globally sets compiler's debug info generation
|
|
||||||
-added consistency check on bytecode serialization
|
|
||||||
-fixed += operator, now works on strings like +
|
|
||||||
-added global slot in the base lib _charsize_ to recognize unicode builds from ascii builds runtime
|
|
||||||
-added registry table
|
|
||||||
-new api call sq_pushregistrytable()
|
|
||||||
-added type tag to the userdata type sq_settypetag()
|
|
||||||
-sq_getuserdata now queries the userdata typetag
|
|
||||||
-the built in function collect_garbage() as been renamed collectgarbage() for consistency reasons
|
|
||||||
-new standard libraries(sqlibs are now obsolete)
|
|
||||||
|
|
||||||
***2004-02-20 ***
|
|
||||||
***version 1.0 beta 1***
|
|
||||||
-fixed a bug in the compiler (thanks Martin Kofler)
|
|
||||||
-fixed bug in the switch case statement
|
|
||||||
-fixed the _unm metamethod
|
|
||||||
-fixed minor bugs in the API
|
|
||||||
-fixed automatic stack resizing
|
|
||||||
-first beta version
|
|
||||||
first pass code clean up in the VM and base lib
|
|
||||||
first pass code coverege test has been done on VM and built-in lib
|
|
||||||
-new VM creation API sq_open() sq_close() (sq_newvm and sq_releasevm are now obsolete)
|
|
||||||
-new api allows to specifiy a "print" function to output text(sq_printfunc)
|
|
||||||
-added some small optimizations
|
|
||||||
-new cooperative multi-threading capabilities in the base library(coroutines), VMs are now a built in type("thread")
|
|
||||||
-new built in functions have been added for manipulating the new "thread" type
|
|
||||||
-friend virtual machines share the same root table, error handler and debug hook by default
|
|
||||||
-new compile time options
|
|
||||||
|
|
||||||
***2004-01-19 ***
|
|
||||||
***version 0.9 alpha***
|
|
||||||
-fixed a garbage collection bug
|
|
||||||
-fixed some API bugs(thanks to Joshua Jensen)
|
|
||||||
-fixed tail calls (in the version 0.8 the tail call optimization was erroneously disabled)
|
|
||||||
-new function parameters semantic, now passing a wrong number of parameters generates an exception
|
|
||||||
-native closures have now a built in parameter number checking
|
|
||||||
-sq_rawget and sq_rawset now work also on arrays
|
|
||||||
-sq_getsize now woks also on userdata
|
|
||||||
-the userdata release hook prototype is changed(now passes the size of the userdata)
|
|
||||||
-the lexer reader function now returns an integer instead of a char that allows better error checking on the input(thx Joshua Jensen)
|
|
||||||
-faster compiler
|
|
||||||
-try/catch blocks do not cause any runtime memory allocation anymore
|
|
||||||
|
|
||||||
***2003-12-06 ***
|
|
||||||
***version 0.8 alpha***
|
|
||||||
-fixed a bug that was preventing to have callable userdata throught the metamethod _call
|
|
||||||
-fixed a garbage collection bug
|
|
||||||
-fixed == operator now can compare correctly different types
|
|
||||||
-new built in method getstackinfos(level)
|
|
||||||
-improoved line informations precision for the debug hook
|
|
||||||
-new api call sq_compilebuffer()
|
|
||||||
-new built-in api function compilestring()
|
|
||||||
-new syntactic sugar for function declarations inside tables
|
|
||||||
-the debug API has been finalized
|
|
||||||
|
|
||||||
***2003-11-17 ***
|
|
||||||
***version 0.7 alpha***
|
|
||||||
-fixed critical bug SQInteger the tail call system
|
|
||||||
-fixed bug in the continue statement code generation
|
|
||||||
-fixed func call param issue(thanks to Rewoonenco Andrew)
|
|
||||||
-added _delslot metamethod(thanks to Rewoonenco Andrew)
|
|
||||||
-new multiline string expression ( delimited by <[ and ]> )
|
|
||||||
-normal strings ("") do not allow embedded new line anymore
|
|
||||||
-reduced vm memory footprint(C refs are shared between friend VMs)
|
|
||||||
-new api method sq_deleteslot()
|
|
||||||
-new debug hook event 'r' is triggered when a function returns
|
|
||||||
|
|
||||||
***2003-11-04 ***
|
|
||||||
***version 0.6 alpha***
|
|
||||||
-fixed switch statement(was executing the default case after a break)
|
|
||||||
-sq_call() doesn't pop the closure (just the params)
|
|
||||||
-the vm execution can be suspended from the C API anytime (micro-threads)
|
|
||||||
-new api calls sq_suspendvm() sq_wakeupvm() sq_getvmstate() and sq_reservestack()
|
|
||||||
|
|
||||||
***2003-10-13 ***
|
|
||||||
***version 0.5 alpha***
|
|
||||||
-fixed some minor bug
|
|
||||||
-tested with non ASCII identifiers in unicode mode(I've tried chinese chars)
|
|
||||||
-added built-in function string.find()
|
|
||||||
-the built-in function array.sort() optionally accepts a cmp(a,b) function
|
|
||||||
-the debug hook function now has a new prototype debug_hook(event_type,sourcefile,line,functionname)
|
|
||||||
-fixed some debug info imprecision
|
|
||||||
|
|
||||||
***2003-10-01 ***
|
|
||||||
***version 0.4 alpha***
|
|
||||||
-faster VM
|
|
||||||
-sq_call will pop arguments and closure also in case of failure
|
|
||||||
-fixed a bug in sq_remove
|
|
||||||
-now the VM detects delegation cycles(and throws an exception)
|
|
||||||
-new operators ++ and --
|
|
||||||
-new operator ',' comma operator
|
|
||||||
-fixed some expression precedence issue
|
|
||||||
-fixed bug in sq_arraypop
|
|
||||||
|
|
||||||
***2003-09-15 ***
|
|
||||||
***version 0.3 alpha***
|
|
||||||
-fixed a bug in array::insert()
|
|
||||||
-optional Unicode core(define SQUNICODE or _UNICODE on Win32)
|
|
||||||
-sq_compiler uses a new reader function SQLEXREADFUNC
|
|
||||||
-the debug hook passes 'l' instead of 'line' for line callbacks
|
|
||||||
and 'c' instead of 'call' for call callbacks
|
|
||||||
-new array.extend() bulit-in function
|
|
||||||
-new API sq_clone()
|
|
||||||
|
|
||||||
***2003-09-10 ***
|
|
||||||
***version 0.2 pre-alpha***
|
|
||||||
-new completely reentrant VM (sq_open and sq_close are now obsolete)
|
|
||||||
-sq_newvm() has a new prototype
|
|
||||||
-allocators are now global and linked in the VM
|
|
||||||
-_newslot meta method added
|
|
||||||
-rawset creates a slot if doesn't exists
|
|
||||||
-the compiler error callback pass the vm handle(thanks Pierre Renaux)
|
|
||||||
-sq_setforeignptr() sq_getforeingptr() are now public
|
|
||||||
-sq_resume() now is possible to resume generators from C
|
|
||||||
-sq_getlasterror() retrieve the last thrown error
|
|
||||||
-improved docs
|
|
||||||
|
|
||||||
***2003-09-06 ***
|
|
||||||
***version 0.1 pre-alpha***
|
|
||||||
first release
|
|
@ -1,23 +0,0 @@
|
|||||||
|
|
||||||
SQUIRREL=.
|
|
||||||
MAKE=make
|
|
||||||
|
|
||||||
sq32:
|
|
||||||
cd squirrel; $(MAKE)
|
|
||||||
cd sqstdlib; $(MAKE)
|
|
||||||
cd sq; $(MAKE)
|
|
||||||
|
|
||||||
sqprof:
|
|
||||||
cd squirrel; $(MAKE) sqprof
|
|
||||||
cd sqstdlib; $(MAKE) sqprof
|
|
||||||
cd sq; $(MAKE) sqprof
|
|
||||||
|
|
||||||
sq64:
|
|
||||||
cd squirrel; $(MAKE) sq64
|
|
||||||
cd sqstdlib; $(MAKE) sq64
|
|
||||||
cd sq; $(MAKE) sq64
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(MAKE) -C squirrel clean
|
|
||||||
$(MAKE) -C sqstdlib clean
|
|
||||||
$(MAKE) -C sq clean
|
|
@ -1,22 +0,0 @@
|
|||||||
The programming language SQUIRREL 2.2.5 stable
|
|
||||||
|
|
||||||
--------------------------------------------------
|
|
||||||
The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and
|
|
||||||
Linux(Slackware 9.0 on Intel x86, Fedora Core 4 on AMD x64).
|
|
||||||
|
|
||||||
Has been tested with the following compilers:
|
|
||||||
MS Visual C++ 6.0,7.0,7.1 and 8.0 (32 and 64bits)
|
|
||||||
MinGW gcc 3.2 (mingw special 20020817-1)
|
|
||||||
Cygnus gcc 3.2
|
|
||||||
Linux gcc 3.2.3
|
|
||||||
Linux gcc 4.0.0 (x86 64bits)
|
|
||||||
|
|
||||||
|
|
||||||
Feedback and suggestions are appreciated
|
|
||||||
project page - http://www.squirrel-lang.org
|
|
||||||
community forums - http://www.squirrel-lang.org/Forums
|
|
||||||
wiki - http://wiki.squirrel-lang.org
|
|
||||||
author - alberto@demichelis.net
|
|
||||||
|
|
||||||
END OF README
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue